Liaison I2C entre arduino et carte relais

Bonsoir,

J’ai pour project de réalisé un système de tir pour artifices avec des arduino (émetteur et récepteur) reliés par un bus I2C transmis avec 2 cartes RS485.

Dans l’émetteur, il y a pour la partie électronique :

  • un arduino Méga2560
  • 40 boutons
  • 40 résistances
  • 1 carte RS485
  • 1 petit transfo 5VDC
  • 1 batterie 12VDC

J’ai commencé a écrire le code avec 5 boutons sans la carte RS485, je passe par l’arduino (A4, A5) pour la liaison)

#include <Wire.h>
int bouton1Pin=2;    // on dit que le bouton1 est branché sur le pin2 ect...
int bouton2Pin=3;
int bouton3Pin=4;
int bouton4Pin=7;
int bouton5Pin=6;
int bouton1;
int bouton2;
int bouton3;
int bouton4;
int bouton5;

void setup()
{
Wire.begin(); // Rejoindre le bus I2C (Pas besoin d adresse pour le maitre)
pinMode(bouton1Pin, INPUT);
pinMode(bouton2Pin, INPUT);
pinMode(bouton3Pin, INPUT);   // on dit que les Pin des boutons sont des entrés
pinMode(bouton4Pin, INPUT);
pinMode(bouton5Pin, INPUT);
}

void loop(){
bouton1 = digitalRead(bouton1Pin);
//contenu du programme
if(bouton1==HIGH){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(1); // Envoi un 1
Wire.endTransmission(); // Fin de la transmission
}
if(bouton1==LOW){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(0); // Envoi un 0
Wire.endTransmission(); // Fin de la transmission // fin du 1er bouton
}

bouton2 = digitalRead(bouton2Pin);
//contenu du programme
if(bouton2==HIGH){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(3); // Envoi un 3
Wire.endTransmission(); // Fin de la transmission
}
if(bouton2==LOW){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(2); // Envoi un 2
Wire.endTransmission(); // Fin de la transmission  // fin du 2nd bouton
}

bouton3 = digitalRead(bouton3Pin);
//contenu du programme
if(bouton3==HIGH){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(5); // Envoi un 5
Wire.endTransmission(); // Fin de la transmission
}
if(bouton3==LOW){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(4); // Envoi un 4
Wire.endTransmission(); // Fin de la transmission  // fin du 3eme bouton
}

bouton4 = digitalRead(bouton4Pin);
//contenu du programme
if(bouton4==HIGH){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(7); // Envoi un 7
Wire.endTransmission(); // Fin de la transmission
}
if(bouton4==LOW){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(6); // Envoi un 6
Wire.endTransmission(); // Fin de la transmission  // fin du 4eme bouton
}

bouton5 = digitalRead(bouton5Pin);
//contenu du programme
if(bouton5==HIGH){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(9); // Envoi un 9
Wire.endTransmission(); // Fin de la transmission
}
if(bouton5==LOW){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(8); // Envoi un 8
Wire.endTransmission(); // Fin de la transmission // fin du 5eme bouton
}
}

Jusque là, tout va bien.

Ensuite pour le récepteur :

  • 1 arduino Uno ou Nano
  • 1 RS485
  • 4 carte de 8 relais
  • 4 carte PCF8574 (pour communiquer avec les relais en seulement 2 fils)
  • 1 petit transfo de 5VDC
  • 1 survolteur 60VDC
  • 2 batterie 12VDC
  • divers inters
  • 40 led + resistances (pour controler les lignes)
  • 20 prises haut parleur

Pour commencer, j’ai écrit le code avec 1 PCF8574 et 1 carte de 8 relais sans le RE485 pour le moment (c’est déjà assez complexe comme çà :confused: )
J’ai aussi fait communiqué l’arduino Uno avec le PC pour controler les données passantes.

#include <Wire.h> // Librairie pour la communication I2C



void setup()
{
Wire.begin(4); // Rejoindre le bus à l'adresse #4
Wire.onReceive(receiveEvent); // Preparer une fonction spécifique a la reception de donnee
Serial.begin(9600); // Demarrer la liaison serie avec le PC
}

void loop()
{
delay(100);
}

// Fonction qui s execute si quelque chose est present sur l interface
void receiveEvent(int howMany)
{
int x = Wire.read(); // recevoir un chiffre
Serial.println(x); // afficher ce chiffre sur l'interface serie
if(x == 0)
{
Write(B11111111);  // écrit une valeur binaire si il reçoit un chiffre x
}
if(x == 1)
{
Write(B11111110);
}
if(x == 2)
{
Write(B11111111);
}
if(x == 3)
{
Write(B11111101);
}
if(x == 4)
{
Write(B11111111);
}
if(x == 5)
{
Write(B11111011);
}
if(x == 6)
{
Write(B11111111);
}
if(x == 7)
{
Write(B11110111);
}
if(x == 8)
{
Write(B11111111);
}
if(x == 9)
{
Write(B11101111);
}
if(x == 10)
{
Write(B11111111);
}
if(x == 11)
{
Write(B10111111);
}
if(x == 12)
{
Write(B11111111);
}
if(x == 13)
{
Write(B01111111);
}
}

void Write(byte _data) {
 Wire.beginTransmission(0x20);  // transmission du binaire au PCF8574
 Wire.write(_data);
 Wire.endTransmission();
}

Le but c’est que quand j’appuie sur le bouton 1 de l’émetteur, le relais 1 du récepteur se ferme pour envoyer du courant vers l’artifice.
Mon soucis c’est que les 2 arduino ne communiquent pas
Lorsque je ne met pas cette ligne de code

void Write(byte _data) {
 Wire.beginTransmission(0x20);
 Wire.write(_data);
 Wire.endTransmission();
}

Ils communiquent. Je comprend pas, pourtant j’ai pensé à définir leurs status (Méga2560 maitres Wire.begin(); et Uno esclave Wire.begin(4).

Je pense qu’il faut que l’esclave renvoie le binaire dans le bus vers le PCF8574 (son adresse est 0x20) mais je sais pas comment faire :-\

Je précise que les arduino et le PCF8574 sont branchés sur le même bus.

Pouvez vous m’aider ?

I2C transmis avec 2 cartes RS485

Bonjour,
il y a peut-être déjà là une confusion, normalement :

  • l'I2C permet à un arduino de communiquer avec les PCF8574 en utilisant une librairie wire
  • le RS485 permet aux arduino de communiquer entre eux en utilisant une librairie serial

par ailleurs :

  • ton topic est un peu sec, on aime bien les images
  • lors de la construction d'un programme, il vaut mieux procéder par étape : faire une fonction, la valider, puis passer à la suivante

Alors, j’ai commencé par essayer la liaison entre les deux arduino (Méga2560 avec les boutons) et (Uno avec les led).

Dans l’arduino Méga 2560 (maitre) j’avais se code.

#include <Wire.h>
int bouton1Pin=2;    // on dit que le bouton1 est branché sur le pin2 ect...
int bouton2Pin=3;
int bouton3Pin=4;
int bouton4Pin=7;
int bouton5Pin=6;
int bouton1;
int bouton2;
int bouton3;
int bouton4;
int bouton5;

void setup()
{
Wire.begin(); // Rejoindre le bus I2C (Pas besoin d adresse pour le maitre)
pinMode(bouton1Pin, INPUT);
pinMode(bouton2Pin, INPUT);
pinMode(bouton3Pin, INPUT);   // on dit que les Pin des boutons sont des entrés
pinMode(bouton4Pin, INPUT);
pinMode(bouton5Pin, INPUT);
}

void loop(){
bouton1 = digitalRead(bouton1Pin);
//contenu du programme
if(bouton1==HIGH){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(1); // Envoi un 1
Wire.endTransmission(); // Fin de la transmission
}
if(bouton1==LOW){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(0); // Envoi un 0
Wire.endTransmission(); // Fin de la transmission // fin du 1er bouton
}

bouton2 = digitalRead(bouton2Pin);
//contenu du programme
if(bouton2==HIGH){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(3); // Envoi un 3
Wire.endTransmission(); // Fin de la transmission
}
if(bouton2==LOW){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(2); // Envoi un 2
Wire.endTransmission(); // Fin de la transmission  // fin du 2nd bouton
}

bouton3 = digitalRead(bouton3Pin);
//contenu du programme
if(bouton3==HIGH){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(5); // Envoi un 5
Wire.endTransmission(); // Fin de la transmission
}
if(bouton3==LOW){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(4); // Envoi un 4
Wire.endTransmission(); // Fin de la transmission  // fin du 3eme bouton
}

bouton4 = digitalRead(bouton4Pin);
//contenu du programme
if(bouton4==HIGH){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(7); // Envoi un 7
Wire.endTransmission(); // Fin de la transmission
}
if(bouton4==LOW){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(6); // Envoi un 6
Wire.endTransmission(); // Fin de la transmission  // fin du 4eme bouton
}

bouton5 = digitalRead(bouton5Pin);
//contenu du programme
if(bouton5==HIGH){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(9); // Envoi un 9
Wire.endTransmission(); // Fin de la transmission
}
if(bouton5==LOW){
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(8); // Envoi un 8
Wire.endTransmission(); // Fin de la transmission // fin du 5eme bouton
}
}

Et dans l’ uno 'esclave).

#include <Wire.h> // Librairie pour la communication I2C

const int L1 = 2; // broche 2 du micro-contrôleur se nomme maintenant : L1
const int L2 = 3;
const int L3 = 4;
const int L4 = 7;
const int L5 = 6;
 
void setup()
{
Wire.begin(4); // Rejoindre le bus à l'adresse #4
Wire.onReceive(receiveEvent); // Preparer une fonction spécifique a la reception de donnee
Serial.begin(9600); // Demarrer la liaison serie avec le PC
pinMode(L1, OUTPUT); // L1 est une broche de sortie
pinMode(L2, OUTPUT);
pinMode(L3, OUTPUT);
pinMode(L4, OUTPUT);
pinMode(L5, OUTPUT);
}

void loop()
{
delay(100);
}

// Fonction qui s execute si quelque chose est present sur l interface
void receiveEvent(int howMany)

{
int x = Wire.read(); // recevoir un chiffre
Serial.println(x); // afficher ce chiffre sur l'interface serie
if(x == 1)
{
digitalWrite(L1, HIGH); // allumer L1
}
if(x == 0)
{
digitalWrite(L1, LOW); // eteindre L1
}
if(x == 3)
{
digitalWrite(L2, HIGH); // allumer L2
}
if(x == 2)
{
digitalWrite(L2, LOW); // eteindre L2
}
if(x == 5)
{
digitalWrite(L3, HIGH); // allumer L3
}
if(x == 4)
{
digitalWrite(L3, LOW); // eteindre L3
}
if(x == 7)
{
digitalWrite(L4, HIGH); // allumer L4
}
if(x == 6)
{
digitalWrite(L4, LOW); // eteindre L4
}
if(x == 9)
{
digitalWrite(L5, HIGH); // allumer L5
}
if(x == 8)
{
digitalWrite(L5, LOW); // eteindre L5
}
}

Sur le logiciel arduino, sur le moniteur de série, on peut voir les valeurs transmisent. Jusque là tout fonctionne bien.

Ensuite, j’ai essayé de me familiariser avec le module relais commendé par un PCF8574

J’ai juste fait activé les relais 1 à 1 toute les demi seconde.

Sur le PCF8574 j’ai relié les bornes A0, A1, A3 pour que l’adresse soit 0x20

#include <Wire.h>

#define adress 0x20


void setup() {
 Wire.begin();
}

void loop() {
 Write(B11111110);  // On passe P1 à 1 et les autre à 0 pour allumer la LED
 delay(500);       // On attend 1s (1000ms)
 Write(B10111111);  // On passe tout à 1 pour etteindre la LED
 delay(500);       // On attend 1s (1000ms)
 Write(B11111011);  // On passe P1 à 1 et les autre à 0 pour allumer la LED
 delay(500);       // On attend 1s (1000ms)
 Write(B11110111);  // On passe tout à 1 pour etteindre la LED
 delay(500);       // On attend 1s (1000ms)
 Write(B11101111);  // On passe P1 à 1 et les autre à 0 pour allumer la LED
 delay(500);       // On attend 1s (1000ms)
 Write(B11011111);  // On passe tout à 1 pour etteindre la LED
 delay(500);       // On attend 1s (1000ms)
 Write(B11111101);  // On passe P1 à 1 et les autre à 0 pour allumer la LED
 delay(500);       // On attend 1s (1000ms)
 Write(B01111111);  // On passe tout à 1 pour etteindre la LED
 delay(500);       // On attend 1s (1000ms)
}

void Write(byte _data) {
 Wire.beginTransmission(adress); // Commence la transmission sur l'adresse défini plus haut
 Wire.write(_data);              // On envoie la donnée
 Wire.endTransmission();         // On termine la transmission
}

Tout fonctionnait bien et après ça va se compliquer

JustinPirolley:
Bonsoir,

J'ai pour project de réalisé un système de tir pour artifices avec des arduino (émetteur et récepteur) reliés par un bus I2C transmis avec 2 cartes RS485.

Bonjour
je n'a pas bien saisi ton concept I²C/RS485 ?

distance entre entre les 2 arduino ?

En fait pour répondre a ta question,

Les 2 arduino communiqueront ensembles grâce aux cartes rs485. Puis l'arduino récepteur communiquera avec 4 PCF8574 en I2C.
J'ai appris plus haut sur le forum que les cartes rs485 ne communique pas avec de l'I2C mais en Sérial.

Je termine les schémas du dernier montage pour expliquer mon problème

JustinPirolley:
En fait pour répondre a ta question,

Les 2 arduino communiqueront ensembles grâce aux cartes rs485. Puis l'arduino récepteur communiquera avec 4 PCF8574 en I2C.
J'ai appris plus haut sur le forum que les cartes rs485 ne communique pas avec de l'I2C mais en Sérial.

Je termine les schémas du dernier montage pour expliquer mon problème

OK

Pour le moment, je n’est pas les 2 cartes rs485. Alors je voulait essayer de faire communiquer les 2 arduino via le bus I2C.
Explication :

  • L’arduino Méga2560 envoie les informations des boutons sur le bus.
  • L’arduino Uno récupère des informations du bus puis renvoie un information vers le PCF8574 pour activer les relais.

Le code de l’arduino Méga2560 est toujours le même, mais pas pour l’arduino Uno. Depuis que j’ai écrit le code qui envoie les informations vers le PCF8574, ca ne fonctionne pas. Même dans le moniteur de série, aucune info.

Le code de l’arduino Uno

#include <Wire.h> // Librairie pour la communication I2C



void setup()
{
Wire.begin(4); // Rejoindre le bus à l'adresse #4
Wire.onReceive(receiveEvent); // Preparer une fonction spécifique a la reception de donnee
Serial.begin(9600); // Demarrer la liaison serie avec le PC
}

void loop()
{
delay(100);
}

// Fonction qui s execute si quelque chose est present sur l interface
void receiveEvent(int howMany)
{
int x = Wire.read(); // recevoir un chiffre
Serial.println(x); // afficher ce chiffre sur l'interface serie
if(x == 0)
{
Write(B11111111);  // écrit une valeur binaire si il reçoit un chiffre x
}
if(x == 1)
{
Write(B11111110);
}
if(x == 2)
{
Write(B11111111);
}
if(x == 3)
{
Write(B11111101);
}
if(x == 4)
{
Write(B11111111);
}
if(x == 5)
{
Write(B11111011);
}
if(x == 6)
{
Write(B11111111);
}
if(x == 7)
{
Write(B11110111);
}
if(x == 8)
{
Write(B11111111);
}
if(x == 9)
{
Write(B11101111);
}
if(x == 10)
{
Write(B11111111);
}
if(x == 11)
{
Write(B10111111);
}
if(x == 12)
{
Write(B11111111);
}
if(x == 13)
{
Write(B01111111);
}
}

void Write(byte _data) {
 Wire.beginTransmission(0x20);  // transmission du binaire au PCF8574
 Wire.write(_data);
 Wire.endTransmission();
}

J’ai du faire une erreur qui coupe la communication mais je sais pas laquelle ?

Qui pourrait me donner un conseil ou des explications ?

Bonjour,
alors un conseil : si tu dois à terme faire communiquer les cartes en rs485, fais l’essai sur ta maquette en reliant les 2 arduinos par une liaison série (ne pas compliquer en les reliant par l’i2c déjà utilisé vers les pcf8574) :
ardu1_tx → ardu2_rx
ardu1_rx ← ardu2_tx
gnd <_> gnd

pour commencer fais un simple programme pour échanger des données, dans un sens, puis dans l’autre, puis les 2 sens (réponse)
pour débuter tu utilises software serial pour les 2 arduinos, voir les exemples sur la toile

puis tu envoies des commandes depuis un arduino vers le 2ème, qui les traduira en actions à faire sur les pcf8574

puis tu reviens nous voire pour la suite

Bien, Merci

Bonjour,

J'ai réussi à envoyer des info sur un arduino depuis le moniteur de série et à réceptionner des info sur le moniteur de série depuis l'arduino. (en serial) en me basant sur des tutos du net

Mais ça se compliquer lorsque je les fait communiquer entre eux. J'ai écrit deux petit codes : lorsque j'appuie sur le bouton1 de l'arduino méga, la led1 de l'arduino uno s'allume et même chose pour le bouton2.
Mon soucis c'est que les led s'allument avec une très faible intensité !?

Code Maitre

int bouton1Pin=2;    // on dit que le bouton1 est branché sur le pin2 ect...
int bouton2Pin=3;

int bouton1;
int bouton2;


void setup(){
Serial.begin(9600);
pinMode(bouton1Pin, INPUT);
pinMode(bouton2Pin, INPUT);
}

void loop(){
  bouton1 = digitalRead(bouton1Pin);
  if(bouton1==HIGH){
  Serial.write(65); // écrit la valeur 65 sur le port de série)
  }
  bouton2 = digitalRead(bouton2Pin);
  if(bouton2==HIGH){
    Serial.write(66);
  }
  }

Le code Esclave

const int L1 = 2;
const int L2 = 3;

void setup(){
  pinMode(L1,OUTPUT);
  pinMode(L2,OUTPUT); 
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()>0)
  {
    char letter = Serial.read();

    if(letter == 65)
    {
      digitalWrite(L1,HIGH);
      digitalWrite(L1,LOW);
    }
    if(letter == 66)
    {
      digitalWrite(L2,HIGH);
      digitalWrite(L2,LOW);
    }
}
}

La led Tx de l'arduino Maitre s'allume lorsque j'appui sur le bouton mais la led Rx de l'arduino Esclave ne s'allume pas.
Je ne comprend pas pourquoi ? - Si quelqu'un peut m'expliquer l'erreur

hello
tu n'as pas inversé les n° des leds

if(letter == 66)
{
digitalWrite(L2,HIGH);
digitalWrite(L2,LOW);
}

ne devrais tu pas avoir L1 au lieu de L2 ?

Normalement, lorsque j'appui sur le bouton1, la led1 s'allume et dès que je le relâche la led s'éteind et c'est la même chose pour le bouton2 et la led2.

65 c'est la valeur transmise par le bouton1
66 c'est la valeur transmise par le bouton2

Ce n'est pas une erreur, mais je ne comprend pas pourquoi les led s'allume faiblement ??

parce que tant que ton doigt est sur le BP, le prg passe son temps à:

allumer/eteindre/allumer/eteindre/allumer/eteindre/allumer/eteindre/...sans cesse

Donc il faudrait que je mette un petit delay par exemple ou envoyer en permanence un variable pour que la led reste éteinte lorsque l'on relâche le bouton

Bonjour,
oui, si tu veux des envois itératifs. Si non tu subordonnes tout nouvel envoi à un relâchement précédent : dans ce cas il faut garder l'état précédent en mémoire.

J'ai mis une valeurs pour chaque états des boutons et sa fonctionne bien
Maintenant je vais essayer d'inclure le bus i2c en reliant les relais

Je rencontre un problème quand je met une valeur pour chaque états des boutons. Les led des relais s'allume mais ils ne claques pas.
Lorsque je met un petit delay de 10ms, il fonctionne. Pourquoi ça fonctionne pas ? par la suite j'aimerai déclencher des séries de 10 relais espacé de 100ms avec un seul bouton.

Exemple sans délai

void loop() {
  if(Serial.available()>0)
  {
    char letter = Serial.read();

    if(letter == 1)           // la valeur 1 allume la led 1 du module relais et le déclanche
    {
      Write(B11111110);  
    }
    if(letter == 2)          // la valeur 2 éteint la led 1 et le relais 1 du module
    {
      Write(B11111111);
    }
    if(letter == 3)          // la valeur 3 allume la led 2 du module relais et le déclanche
    {
      Write(B11111101);
    }
     if(letter == 4)        // la valeur 4 éteint la led 2 et le relais 2 du module 
    {
     Write(B11111111);
     }

Avec délai

void loop() {
  if(Serial.available()>0)
  {
    char letter = Serial.read();

    if(letter == 1)
    {
      Write(B11111110);
      delay(10);               // la valeur 1 allume la led 1 du module relais et déclanche le relais      Write(B11111111);          // pendant 10ms
    }
    if(letter == 3)
    {
      Write(B11111101);
       delay(10);            // la valeur 3 allume la led 2 du module relais et déclanche le relais
      Write(B11111111);  // pendant 10ms
    }

Les led des relais s’allume mais ils ne claques pas

Bonjour,
c’est comme si tu étais toujours dans le travers :

allumer/eteindre/allumer/eteindre/allumer/eteindre/allumer/eteindre/…sans cesse

que dit le moniteur à propos des messages reçus quand tu appuies sur le bouton ?