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 :

Lire les ports d'un expandeur de bus MCP23016


Sujet :

Raspberry Pi

  1. #1
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut Lire les ports d'un expandeur de bus MCP23016
    bonjour,
    je dois utiliser un expandeur de bus I2C MCP23016 avec la librairie wiringPiI2C sur mon système.
    I2cdetect détecte le MPC sans problème entre les adresses de base 0x20 et 0x27 mais mon programme retourne généralement la valeur -1.

    J'ai écrit ces lignes dans un programme de test pour lire les entrées du port GP0:
    Code c++ : 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
     
    #include <mcp23016.h>
    #include <wiringPi.h>
    #include <wiringPiI2C.h>
     
    using namespace std;
     
    int main()
    {
      int fd;
     
      fd = wiringPiI2CSetup(0x27) ;
      mcp23016Setup(66, 0x27);
     
      wiringPiI2CWriteReg16(fd, 0x04, 0x00);	//Input_Polarity_Register
      wiringPiI2CWriteReg16(fd, 0x06, 0xff); 	//GP0 as input port
      cout << " Read GP0 : " << wiringPiI2CReadReg8(fd, 0x00) << endl;
     
      return(0);
    }

    Quelques fois, je lis la bonne valeur mais le plus souvent, je lis -1.
    Sur la sortie TP du MCP23016, j'ai un beau signal carré à 1,3MHz.
    Si quelqu'un a déjà mis en oeuvre ce composant, je suis preneur d'une solution.

    Merci.

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


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

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12 620
    Points : 56 857
    Points
    56 857
    Billets dans le blog
    40
    Par défaut
    Bonjour,

    Tu peux rajouter des affichages pour voir d'où vient l'erreur exactement :

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <errno.h>
    ...
     
    fd = wiringPiI2CSetup(0x27) ;
     
    if (fd==-1) {cout << "erreur ici" << endl;}
     
    ...
     
    int a=wiringPiI2CWriteReg16(fd, 0x04, 0x00);	//Input_Polarity_Register
    if (a==-1) {cout << "erreur là, errno = " << errno << endl;}
     
    ...

  3. #3
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    bonjour et merci pour la réponse,
    j'avais exploité dans la foulée la valeur de errno dans un appel à perror() et j'ai systématiquement une erreur 121 Remote I/O error.
    Pour l'instant, je ne comprend pas d'où ça sort. Le MCP 23016 est seul sur la carte avec ses 3 résistances de configuration d'adresse et son bus I2C. Je l'alimente avec le +5v issu du Raspberry.
    J'investigue mais je n'ai pas trop d'idées. Je farfouille sur le Net.

    Merci.

  4. #4
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 190
    Points : 11 573
    Points
    11 573
    Par défaut
    Salut,
    Donc tu dis que ça fonctionne par moment ?
    On peut voir ton schéma de câblage, le schéma exacte avec tout dessus ?

    A+
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  5. #5
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    bonjour,
    voici la partie I2C de ma carte que je teste pour l'instant sur une breadboard n'ayant pas encore le PCB.
    Nom : partieI2C.jpg
Affichages : 704
Taille : 34,3 Ko
    Le connecteur J3 est relié aux broches SDA et SCL du Raspberry. Pas de cavaliers sur J5.
    J'utilise l'alimentation +5v du Raspberry et je positionne les entrées des ports GP0 et GP1 par straps.
    SDA et SCL sont à 3,7v (pull-up du Raspberry), je vais tenter d'alimenter le MCP23016 avec l'alim 3,3v du Raspberry.

    Je ne vais quand même pas mettre en cause les fonctions WiringPi...
    Je fais ma manip et je rend compte.

    Merci.

  6. #6
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    Re,
    j'ai alimenté l'expandeur de bus en 3,3v en provenance du Raspberry.
    Plus aucune erreur à l'exécution de mon programme mais j'ai toujours 255 à la lecture du port GP0.
    J'ai laissé GP0 en entrée et programmé GP1 en sortie avec une led sur le bit 0 de GP1.
    Les bits 0 et 1 de GP0 sont forcés à 0, les bits 2 et 3 à +3,3v.
    Code : 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
    int main()
    {
      int fd, retour = 0, i;
    
      fd = wiringPiI2CSetup(0x27);
      if(fd < 0)
      {
        perror("wiringPiI2CSetup");
        exit(-1);
      }
      retour = mcp23016Setup(80, 0x27);
     
      retour = wiringPiI2CWriteReg16(fd,0x04,0x00); //sorties non inversees
      if(retour == -1)
        perror("pb sorties non inversees");
    
      retour = wiringPiI2CWriteReg8(fd,0x06,0xff); //GP0 en entree
      if(retour == -1)
        perror("pb GP0 en entree");
    
      retour = wiringPiI2CWriteReg8(fd,0x07,0x00); //GP1 en sortie
      if(retour == -1)
        perror("pb GP1 en sortie");
    
      cout << "Read du Registre GP0 : " << wiringPiI2CReadReg8(fd,0x00) << endl;
      for(i=0; i<20; i++)
      {
        retour = wiringPiI2CWriteReg8(fd, 0x01, i%2);
        if(retour == -1)
          perror("pb pilotage led");
        sleep(1);
      }
      return(0);
    }
    La led clignote mais je ne comprend pas pourquoi je ne vois pas les 2 bits de poids faibles à 0 sur le "Read du Registre GP0". Si j'avais eu 0x00 comme résultat, j'aurais compris que le MCP23016 n'est peut être pas trop à l'aise en 3,3v et qu'il interprète ce niveau en entrée comme un 0.
    Peut être un adaptateur de niveau sur le bus I2C pour continuer à alimenter le MCP en +5v (genre TCA9406) ?

    Merci pour vos avis.

  7. #7
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 190
    Points : 11 573
    Points
    11 573
    Par défaut
    Salut,
    Citation Envoyé par rdtech Voir le message
    j'ai alimenté l'expandeur de bus en 3,3v en provenance du Raspberry.
    Plus aucune erreur à l'exécution de mon programme
    Électriquement tu es dans le cas normal là.

    Le bus I2C est a collecteur/drain ouvert et donc nécessite des résistances de pull-up pour fonctionner et elles doivent être reliées à la même tension que le composant.
    Dans le premier cas, tu avais ton MCP23016 alimenté en +5V avec des résistances de pull-up reliées au +3.3V du Raspberry et ça c'est pas très bon.

    Tu t'es remis ici dans un fonctionnement correct :
    MCP23016 alimenté en +3.3V
    Rpull-up sur le +3.3V
    Raspberry a ses sorties en +3.3V
    Et 0V commun évidemment

    Côté Soft :
    Code C : 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
     
    int main()
    {
      int fd, retour = 0, i;
     
      fd = wiringPiI2CSetup(0x27);
      if(fd < 0)
      {
        perror("wiringPiI2CSetup");
        exit(-1);
      }
      retour = mcp23016Setup(80, 0x27);
     
      retour = wiringPiI2CWriteReg16(fd,0x04,0x00); //sorties non inversees
      if(retour == -1)
        perror("pb sorties non inversees");
     
      retour = wiringPiI2CWriteReg8(fd,0x06,0xff); //GP0 en entree
      if(retour == -1)
        perror("pb GP0 en entree");
     
      retour = wiringPiI2CWriteReg8(fd,0x07,0x00); //GP1 en sortie
      if(retour == -1)
        perror("pb GP1 en sortie");
     
      cout << "Read du Registre GP0 : " << wiringPiI2CReadReg8(fd,0x00) << endl;
      for(i=0; i<20; i++)
      {
        retour = wiringPiI2CWriteReg8(fd, 0x01, i%2);
        if(retour == -1)
          perror("pb pilotage led");
        sleep(1);
      }
      return(0);
    }

    Ton code à l'air de bien configurer l'I/O expender.

    Nom : Capture du 2017-03-29 23-42-45.png
Affichages : 670
Taille : 166,4 Ko

    1) Dans ton code je vois wiringPiI2CWriteReg16(fd,0x04,0x00); //sorties non inversees c'est normal le Reg16 ?
    2) C'est quoi cette ligne ? mcp23016Setup(80, 0x27); je ne comprends pas le 80 ?

    Ensuite ça c'est normal wiringPiI2CWriteReg8(fd, 0x01, i%2); tu écris bien sur des sorties

    Il ne me semble pas y avoir de problèmes de soft mis à part les questions 1) et 2) juste au dessus !



    Côté Hard :
    Citation Envoyé par rdtech Voir le message
    mais j'ai toujours 255 à la lecture du port GP0.
    J'ai laissé GP0 en entrée et programmé GP1 en sortie avec une led sur le bit 0 de GP1.
    Les bits 0 et 1 de GP0 sont forcés à 0, les bits 2 et 3 à +3,3v.
    La led clignote mais je ne comprend pas pourquoi je ne vois pas les 2 bits de poids faibles à 0 sur le "Read du Registre GP0". Si j'avais eu 0x00 comme résultat, j'aurais compris que le MCP23016 n'est peut être pas trop à l'aise en 3,3v et qu'il interprète ce niveau en entrée comme un 0.
    Peut être un adaptateur de niveau sur le bus I2C pour continuer à alimenter le MCP en +5v (genre TCA9406) ?
    Il me faut un schéma (complet ) parce que c'est surement clair pour toi car tu es devant le montage mais pour quelqu'un qui te lit c'est loin de l'être.
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  8. #8
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    bonjour,
    j'utilise la librairie wiringpi qui permet d'accéder au bus I2C depuis le Raspberry avec notamment une extension pour le MCP23016 d'où mcp23016Setup(80, 0x27);
    La doc dit:
    mcp23017Setup (int pinBase, int i2cAddress) ; //The pinBase can be any number you like above 64 and the i2cAddress is the address of the device in the I2C bus
    J'ai pris la valeur 80 car elle est supérieur à 64, why not?
    wiringPiI2CWriteReg16(fd,0x04,0x00); //16 car dans le MCP23016 les registres sont organisés par paires et donc permet de faire un accès à l'adresse 0x04 et 0x05

    J'attend un level shifter pour le bus I2C ce qui me permettra de remettre l'expandeur en 5v et ses entrées itou.
    Le schéma:
    Nom : schema.jpg
Affichages : 681
Taille : 111,1 Ko

    Merci.

  9. #9
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 190
    Points : 11 573
    Points
    11 573
    Par défaut
    Salut,
    On ne voit rien sur ton schéma, je n'arrive pas voir les références des composants.

    Tu ne serai pas entrain de faire un cours circuits entre tes sorties de ton I/O expander et les sorties d'un des composants qui sont sur sa gauche ?

    Faudrait que je vois les références pour comprendre.
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  10. #10
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    bonjour,
    sur la carte que j'ai maintenant, je n'ai implanté que le MCP23016, le circuit RC pour son oscillateur, les 4 résistances de config de l'adresse I2C et la led du 5v.
    J'ai intercalé un level shifter (bss138 ADAFRUIT) sur le bus I2C.
    Les ports GPIO seront attaqués plus tard par deux compteurs 74HC590.
    i2cdetect voit bien le circuit à l'adresse de base 0x27.
    J'ai écrit ces quelques lignes:
    Code : 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
    #define BASE_ADDR 0x27
    
    int main()
    {
            int fd;
            char writeGpio0Cmd[] = {0x4e, 0x00}; //0x4e = 0x27 << 1
            char readGpio0Cmd[] = {0x4f};  //0x4f = 0x27 << 1 + 1
            char gpio0 = 0x00;
    
            fd = open("/dev/i2c-1", O_RDWR);
            if(fd < 0)
            {
                    perror("open");
                    exit(-1);
            }
    
            if(ioctl(fd, I2C_SLAVE, BASE_ADDR) < 0)
            {
                    perror("ioctl");
                    exit(-1);
            }
    
            //par défaut GP0 est configuré en entrée
            //pour lire un registre:
            //send slave address, setting R/W bit to 0, then the command byte
            write (fd, &writeGpio0Cmd[0], sizeof(char));
            write (fd, &writeGpio0Cmd[1], sizeof(char));
            //send slave address, setting R/W bit to 1
            write (fd, readGpio0Cmd, sizeof(readGpio0Cmd));
            read(fd, &gpio0, sizeof(char));
            printf("gpio0 = 0x%x\n", gpio0);
    
            close(fd);
            return 0;
    }
    J'ai forcé les 4 premières lignes de gp0 à 1000 mais le printf m'affiche toujours 0x00 et à la suite de ça, i2cdetect ne détecte plus mon périphérique sur lequel je suis obligé de faire un on/off pour le revoir apparaître.
    J'en perd mon latin...

  11. #11
    Membre confirmé
    Avatar de deletme
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2011
    Messages : 257
    Points : 519
    Points
    519
    Par défaut
    D'après la doc registre GP0:
    A read from this register provides status on pins of
    these ports.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char buf;
    buf = 0x00; // GP0 address
    read(fd, &buf, 1);
    buf contiendra sûrement l'état de GP0
    Une alternative (d'après une expérience "lointaine" : certains device attendent une écriture vide sur le registre visé pour préparer la réponse à la prochaine demande d'écriture) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char buf;
    buf = 0x00; // GP0 address
    write(fd, &buf, 1);
    read(fd, &buf, 1);
    buf contiendra sûrement l'état de GP0

    Tu peux également ajouter des tests sur tes lectures et écritures. write et read retourne le nombre d'octet(s) écrit(s) lu(s). Si ce nombre est différent de la taille demandée ou -1, tu as une erreur à ce niveau là.
    "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."
    - Martin Golding
    Traduction obligatoire : "Toujours écrire du code en gardant en tête que le mec qui en assurera la maintenance est un psychopathe violent qui connait votre adresse"

  12. #12
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    Bonjour deletme,
    c'est ce que j'ai fais dans mon code mais sans résultats.
    J'ai perdu trop de temps avec ce composant. Je l'abandonne au profit d'un PCF8575 que l'on m'a passé et ça fonctionne parfaitement.
    Merci pour vos réponses.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Lire les ports com1 et com2
    Par biquet dans le forum LabVIEW
    Réponses: 4
    Dernier message: 04/11/2008, 16h31
  2. Lire les données sur un port //
    Par gastoncs dans le forum Périphériques
    Réponses: 1
    Dernier message: 20/08/2008, 22h40
  3. Lire les données du port série RS232
    Par Sytchev3 dans le forum Langage
    Réponses: 2
    Dernier message: 16/06/2008, 08h47
  4. Réponses: 20
    Dernier message: 16/11/2007, 12h29
  5. lire les données sur un port RS232
    Par xave dans le forum Langage
    Réponses: 6
    Dernier message: 06/10/2005, 16h40

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