Pilotage carte relais avec MCP23017

bonjour,

je suis entrain de regardé pour piloté une carte 16 relais et une Carte 16 entre opto avec un petit uno et 4 mcp23017 .
mes competence en prog sont limité ^^.

j'aurais voulus savoir si il y une fonction pour facilité l'écriture je voudrais evité d'ecrire 36 x la meme ligne

je voudrais declaré 2mcp complet en tant que sortie et 2 en tant que entré .

 mcp1.begin(0); // Utilise l'adresse 0x20 + 0 pour IC1 relais volet 1-4
  mcp2.begin(5); // Utilise l'adresse 0x20 + 5 pour IC2 relais volet 5-8
  mcp3.begin(6); // Utilise l'adresse 0x20 + 6 pour IC3 bp_volet 1-4
  mcp4.begin(7); // Utilise l'adresse 0x20 + 7 pour IC4 bp_volet 5-8


  // Définir la sortie #0 (GPA 0, broche 21) sur IC1 comme sortie
  mcp1.pinMode(0, OUTPUT);
  // Définir la sortie #1 (GPA 1, broche 22) sur IC2 comme sortie
  mcp2.pinMode(1, INTPUT);

Bonjour diablo673

Excellent reflex :wink:

Quand on a un grand nombre de périphériques à traiter premier truc à étudier, c'est les tableaux. Tableau dans lesquels tu va mettre les mcp:

Adafruit_MCP23X17 mcp[mcpNombre];

comme chaque mcp a une adresse on les mets aussi en tableau:

const int mcpAdresse[ ] = {0, 5, 6, 7};

On peut les "nommer":
enum mcpIndex {mcpRelaisVolet1_4, mcpRelaisVolet5_8, mcpBpVolet1_4, mcpBpVolet5_8};

Ce qui permet de faire une boucle pour les initialiser:

	for (int m = 0; m < mcpNombre; m ++)
	{
		mcp[m].begin(mcpAdresse[m]);
	}

et une boucle pour initialiser tout les ports:

	for (int p = 0; p < 16; p ++)     // Initialisation des 16 ports
	{
		mcp[mcpRelaisVolet1_4].pinMode(p, OUTPUT);
		mcp[mcpRelaisVolet5_8].pinMode(p, OUTPUT);
		mcp[mcpBpVolet1_4].pinMode(p, INPUT_PULLUP);
		mcp[mcpBpVolet5_8].pinMode(p, INPUT_PULLUP);
	}

C'est pas essayé "en vrai", ma ça compile.

const int mcpAdresse[] = {0, 5, 6, 7};
const int mcpNombre = sizeof(mcpAdresse)/sizeof(int);

Adafruit_MCP23X17 mcp[mcpNombre];
enum mcpIndex {mcpRelaisVolet1_4, mcpRelaisVolet5_8, mcpBpVolet1_4, mcpBpVolet5_8};

void setup() 
{
	for (int m = 0; m < mcpNombre; m ++)     // Initialisation des mcp
	{
		mcp[m].begin(mcpAdresse[m]);
	}

	for (int p = 0; p < 16; p ++)     // Initialisation des 16 ports de chaque mcp
	{
		mcp[mcpRelaisVolet1_4].pinMode(p, OUTPUT);
		mcp[mcpRelaisVolet5_8].pinMode(p, OUTPUT);
		mcp[mcpBpVolet1_4].pinMode(p, INPUT_PULLUP);
		mcp[mcpBpVolet5_8].pinMode(p, INPUT_PULLUP);
	}
}

Cordialement
jpbbricole

MERCI pour cette explication je vais essayé de m'en inspiré .

il y a aussi des libraries qui facilitent le travail comme celle de RobTillaart.
Elle permet de manipuler les I/O individuellement, par groupe de 8 ou par groupe de 16.

Bonjour
J'ai testé votre code mais j'ai un soucis avec la déclaration des adresses des MCP23017.
Le fait de mettre const int mcpAdresse[] = {0, 5, 6, 7}; avec la nouvelle librairie Adafruit_MCP23X17 cela ne fonctionne, pas il faut absolument mettre les adresses en Hexa const int mcpAdresse[] = {0x20, 0x25, 0x26, 0x27};

#include <Wire.h>
#include <Adafruit_MCP23X17.h>

const int mcpAdresse[] = {0x22, 0x25, 0x26, 0x27}; // Possibilite de mettre jusqu a 8 adresses
const int mcpNombre = sizeof(mcpAdresse)/sizeof(int);

Adafruit_MCP23X17 mcp[mcpNombre];
enum mcpIndex {Mcp_1, Mcp_2, Mcp_3, Mcp_4};
//adresse I2c  0x22,  0x25,  0x26,  0x27

void setup() 
{
   Wire.begin();
     Serial.begin(9600);
	for (int m = 0; m < mcpNombre; m ++)     // Initialisation des mcp
	{
		mcp[m].begin_I2C(mcpAdresse[m]);
	}

	for (int pin = 0; pin < 16; pin ++)     // Initialisation des 16 ports de chaque mcp
	{
		mcp[Mcp_1].pinMode(pin, OUTPUT);
		mcp[Mcp_2].pinMode(pin, OUTPUT);
	
	}
    // Mise a 0 de toutes les sorties  
          mcp[Mcp_1].writeGPIOA(0x00);
          mcp[Mcp_1].writeGPIOB(0x00);
          mcp[Mcp_2].writeGPIOA(0x00);
          mcp[Mcp_2].writeGPIOB(0x00);
}
void loop() {

  // Test presence des Modules +++ Option
  if (!mcp[Mcp_1].begin_I2C(mcpAdresse[Mcp_1])) {
    Serial.print("Impossible d'initialiser le mcp23017 No 1 a l'adresse 0x");
    Serial.println(mcpAdresse[Mcp_1],HEX);
    while (1);
       }

  if (!mcp[Mcp_2].begin_I2C(mcpAdresse[Mcp_2])) {
    Serial.print("Impossible d'initialiser le mcp23017 No 2 a l'adresse 0x");
    Serial.println(mcpAdresse[Mcp_2],HEX);
    while (1);
      }
 
// Test toutes les Sorties
  for (int i = 0; i < 16; i++) {
    	mcp[Mcp_1].digitalWrite(i, HIGH);  // Toutes les Sorties a 1 alternativement
    	mcp[Mcp_2].digitalWrite(i, HIGH);
    delay(500);
    	mcp[Mcp_1].digitalWrite(i, LOW);  // Toutes les Sorties a 0 alternativement
    	mcp[Mcp_2].digitalWrite(i, LOW); }
delay(1000);
}

Il n'y a que de cette manière pour que code soit compilé
Bravo encore pour le code :grinning:

Bonjour RichardV31

Tu as tout à fait raison, en pratique il faut les adresses des MCP.
J'avais simplement adapté ma réponse au code de @diablo673 afin de démontrer le pratique de l'usage de tableaux quand on a une série de choses à traiter.

Cordialement
jpbbricole

Explication :

Avec les versions 1.XXX de la librairie AdaFruit, l'adresse I2C à passer à la méthode begin() est ZERO, Un, DEUX, etc. La méthode ajoute 0x20 à cette adresse.

Avec les versions 2.XXX de la librairie AdaFruit, celle-ci est unifiée (elle pilote aussi bien les MCP23XXX (I2C) que les MCP23SXX (SPI), la méthode begin change de nom pour begin_I2C() ou begin_SPI(), et l'adresse I2C à passer à la méthode begin_I2C() est bien 0x20, 0x21, 0x22, etc.

Je suggérerais à diablo673 de mettre à jour sa librairie.

effectivement j'avais une vielle version de la librairie .et je m’était basé sur un vieux tuto .

J'ai testé le bout de code cela fonctionne maintenant que les mcp sont configure j'essaye de les intégrés a mon programme mais je bloque de nouveau .....

const byte M1_PIN = 1;  // pin de contrôle du relais montée volet 1
const byte D1_PIN = 3;  // pin de contrôle du relais descente volet 1
const byte BP_M1_PIN = 6;     // pin de contrôle du bouton montée volet 1
const byte BP_D1_PIN = 7;     // pin de contrôle du bouton descente volet 1

#include <Wire.h>
#include <Adafruit_MCP23X17.h>
#include <simpleBouton.h> // http://forum.arduino.cc/index.php?topic=375232.0

simpleBouton BP_M1(BP_M1_PIN);   //Cablage : pin---BP---GND
simpleBouton BP_D1(BP_D1_PIN);   //Cablage : pin---BP---GND



unsigned long chronoVolet1;

const unsigned long trenteSecondes = 30000UL;

enum : byte {REPOS, MONTE, DESCEND} etatVolet1;


void setup()
{
  Serial.begin(9600);
  pinMode(M1_PIN, OUTPUT);
  pinMode(D1_PIN, OUTPUT);
  reposVolet1();
  actualiserBoutons();

}

void actualiserBoutons()
{
  BP_M1.actualiser();
  BP_D1.actualiser();
}

void reposVolet1()
{
  digitalWrite(M1_PIN, HIGH); //on éteint le relay_M1
  digitalWrite(D1_PIN, HIGH); //on éteint le relay_D1
  etatVolet1 = REPOS;
}

void monteVolet1()
{
  digitalWrite(D1_PIN, HIGH);
  delay(500); // pour s'assurer que les 2 relais ne sont pas actifs en même temps
  digitalWrite(M1_PIN, LOW);
  chronoVolet1 = millis();
  etatVolet1 = MONTE;
}

void descendVolet1()
{
  digitalWrite(M1_PIN, HIGH);
  delay(500); // pour s'assurer que les 2 relais ne sont pas actifs en même temps
  digitalWrite(D1_PIN, LOW);
  chronoVolet1 = millis();
  etatVolet1 = DESCEND;
}

void actualiserVolet1()
{
  switch (etatVolet1) {
    case REPOS: // 2 évènements possibles bouton Monter ou Descendre
      if (BP_M1.vientDEtreEnfonce()) monteVolet1();
      else if (BP_D1.vientDEtreEnfonce()) descendVolet1();
      break;

    case MONTE:// 3 évènements possibles bouton Monter ou Descendre ou timeOut
      if (millis() - chronoVolet1 >= trenteSecondes) reposVolet1();
      else if (BP_M1.vientDEtreEnfonce()) reposVolet1();
      else if (BP_D1.vientDEtreEnfonce()) descendVolet1();
      break;

    case DESCEND:// 3 évènements possibles bouton Monter ou Descendre ou timeOut
      if (millis() - chronoVolet1 >= trenteSecondes) reposVolet1();
      else if (BP_M1.vientDEtreEnfonce()) monteVolet1();
      else if (BP_D1.vientDEtreEnfonce()) reposVolet1();
      break;
  }
}



void loop()
{
  actualiserBoutons();
  actualiserVolet1();
}

pour l’instant j'ai un petit programme qui marche correctement en utilisant les E/S du arduino

est il possible de remplacé tout simplement les adressages du arduino par ceux des MCP ?

const byte M1_PIN = 1; //remplacé par MCP1(0)  // pin de contrôle du relais montée volet 1
const byte D1_PIN = 3;  // pin de contrôle du relais descente volet 1
const byte BP_M1_PIN = 6;     // pin de contrôle du bouton montée volet 1
const byte BP_D1_PIN = 7;     // pin de contrôle du bouton descente volet 1

Bonjour
Je fait appel aux connaissances de chacun a propos de la nouvelle librairie Adafruit_MCP23X17 en version 2.
la fonction :

  mcpX.pinMode(pin[0], INPUT);  
  mcpX.pullUp(pin[0], HIGH);    
  mcpX.pinMode(pin[1], INPUT);  
  mcpX.pullUp(pin[1], HIGH); 

mcpX.pullUp(pin, HIGH); a disparue dans cette nouvelle librairie. Y a t-il une autre commande qui la remplace ou les entrées sont automatiquement utilisées en mode pullup avec la résistance interne de 100k
Cordialement a tous :thinking:

INPUT_PULLUP, comme avec une GPIO ARDUINO.

Merci pour la réponse, pourtant j'avais bien regardé les exemples mais cette ligne m'avait échappé

 // configure pin for input with pull up
  mcp.pinMode(BUTTON_PIN, INPUT_PULLUP);

Merci encore, j’espère qu'il n'y a pas d'autres changements

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.