maitre demande etat pin en I2C a l'esclave

bonjour,

comment procéder pour que le maître demande l’état des pin à ou aux l'esclave(s)

ex : maitre demande a esclave quel est l'etat de la pin 11 ------> slave repond ma pin 11 est High (1) ou low (0)

actuellement j'arrive a demander a l'esclave de mettre des pin a l’état High (1) ou low (0) comme ceci :

maitre :

#include <Wire.h>

void setup()
{
Wire.begin(); // Rejoindre le bus I2C (Pas besoin d adresse pour le maitre)
}

void loop()
{
//contenu du programme
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(1); // Envoi un 1
Wire.endTransmission(); // Arreter la transmission
delay(1000); // Attendre 1s
//test
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(2); // Envoi un 1
Wire.endTransmission(); // Arreter la transmission
delay(1000); // Attendre 1s


Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(0); // Envoi un 0
Wire.endTransmission(); // Arreter la transmission
delay(2000); // Attendre 2s
//test
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(3); // Envoi un 0
Wire.endTransmission(); // Arreter la transmission
delay(2000); // Attendre 2s
}

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;
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);
}

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 == 2)
{
digitalWrite(L2, HIGH); // allumer L1
}
if(x == 3)
{
digitalWrite(L2, LOW); // eteindre L1
}
}

merci pour votre aide

cordialement

Salut,

Wire.onRequest() :wink:

Wire.onRequest() revoi des bytes

mai je ne c'est comment faire pour connaitre les état des pin avec des bytes!

je vien de tester ceci :

maitre :

#include <Wire.h>

const int L3 = 3;
void setup()
{
Wire.begin(); // Rejoindre le bus I2C (Pas besoin d adresse pour le maitre)
pinMode(L3, OUTPUT);
Serial.begin(9600); // Demarrer la liaison serie avec le PC
}

void loop()
{
//contenu du programme
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(1); // Envoi un 1
Wire.endTransmission(); // Arreter la transmission
delay(500); // Attendre 1s
//test



Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(2); // Envoi un 1
Wire.endTransmission(); // Arreter la transmission
delay(500); // Attendre 1s


Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(0); // Envoi un 0
Wire.endTransmission(); // Arreter la transmission
delay(500); // Attendre 2s
//test
Wire.beginTransmission(4); // Envoyer vers device #4
Wire.write(3); // Envoi un 0
Wire.endTransmission(); // Arreter la transmission
delay(500); // Attendre 2s






 Wire.requestFrom(4, 2);    // request 6 bytes from slave device #2

  while(Wire.available())    // slave may send less than requested
  { 
    char c = Wire.read(); // receive a byte as character
    Serial.print ("c= ");
    Serial.println(c);         // print the character
    if (c == 'A'){
    digitalWrite(L3, HIGH);
    delay(1000);
    }
    else{
    digitalWrite(L3, LOW);
    }
  }

  delay(100);




}

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;
void setup()
{
Wire.begin(4); // Rejoindre le bus à l'adresse #4
Wire.onReceive(receiveEvent); // Preparer une fonction spécifique a la reception de donnee
Wire.onRequest(requestEvent); // register event
Serial.begin(9600); // Demarrer la liaison serie avec le PC

pinMode(L1, OUTPUT); // L1 est une broche de sortie
pinMode(L2, 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 == 2)
{
digitalWrite(L2, HIGH); // allumer L1
}
if(x == 3)
{
digitalWrite(L2, LOW); // eteindre L1
}
}

void requestEvent()
{
  int x = Wire.read(); // recevoir un chiffre
  if( x== 0){
  Wire.write('10'); // respond with message of 2 bytes
                       // as expected by master
  }
  
  
  if( x== 1){
  Wire.write('11'); // respond with message of 2 bytes
                       // as expected by master
  }
  
  if( x== 2){
  Wire.write('12'); // respond with message of 2 bytes
                       // as expected by master
  }
  
  
  if( x== 3){
  Wire.write('13'); // respond with message of 2 bytes
                       // as expected by master
  }
  
  
  
  
}

le moniteur serie m'affiche :

c= ÿ
c=
c= ÿ
c=
c= ÿ
c=
c= ÿ
c=
c= ÿ
c=

etc.....

Bin renvoi en byte l'état de tes pins

je ne comprend pas ce que vous voulait dire par :

"Bin renvoi en byte l'état de tes pins"

est ce comme dans ce que j'ai fait au dessus ?

Déjà ton maitre ne fait pas de request donc c'est sûr que ton esclave ne répondra jamais ...

Ensuite deux solutions : soit tu renvoi l'état de tous tes pins sur une request et c'est le maitre qui fait le tri, soit tu fais un write() pour lui grosso modo "hey quand je vais te faire une request, renvoi moi le pin n°X" et la tu fais une request et tu renvoi l'état du pin x

j'ai reussi a faire fonctionner comme ceci :

maitre :

 Wire.requestFrom(4, 1);    // request 6 bytes from slave device #2

  while(Wire.available())    // slave may send less than requested
  { 
    int c = Wire.read(); // receive a byte as character
    Serial.print ("c= ");
    Serial.println(c);         // print the character
    if (c == 9){
    digitalWrite(L3, HIGH);
    delay(1000);
    }
    else{
    digitalWrite(L3, LOW);
    }
  }

  delay(500);




}

esclave :

void requestEvent()
{
  int x = Wire.read(); // recevoir un chiffre
  buttonState = digitalRead(bouton1);
  if (buttonState == HIGH) {
    Wire.write(9);
  }
  
  
  

}

y a t'il une solution plus simple ? ou plus efficace """"pour debutant """" :slight_smile:

Wire.read() est inutile pour l'esclave (d'ailleurs tu n'en fait rien du byte reçu)

Si tu veux quelque chose de plus "souple" et lire/écrire sur plusieurs pins :

Maitre

#define SET_PIN 1
#define READ_PIN 0

void setPin(int pin,byte state) {

Wire.beginTransmission(4); 
Wire.write(SET_PIN);  
Wire.write(pin);  
Wire.write(state); 
Wire.endTransmission(); 

}

void printState(int pin) {

Wire.beginTransmission(4); 
Wire.write(READ_PIN);  
Wire.write(pin);  
Wire.endTransmission(); 

Wire.requestFrom(4, 1);    

Serial.print(" Pin n°");
Serial.print(pin);
Serial.print(" à ")
Serial.println(Wire.read());

}

Esclave

void receiveEvent() {

byte x=Wire.read();
byte pin=Wire.read();

if(x==READ_PIN) pinToSend=pin;
else digitalWrite(pin,Wire.read());

}

void requestEvent()

{
  
    Wire.write(digitalRead(pinToSend));
  

}

merci beaucoup pour cette aide

par contre quant je met ce code

maitre :

#include <Wire.h>
#define SET_PIN 1
#define READ_PIN 0
const int L3 = 3;
void setup()
{
Wire.begin(); 
pinMode(L3, OUTPUT);
Serial.begin(9600); 
}

void loop()
{


 delay(100);



}

void setPin(int pin,byte state) {

Wire.beginTransmission(4); 
Wire.write(SET_PIN);  
Wire.write(pin);  
Wire.write(state); 
Wire.endTransmission(); 

}

void printState(int pin) {

Wire.beginTransmission(4); 
Wire.write(READ_PIN);  
Wire.write(pin);  
Wire.endTransmission(); 

Wire.requestFrom(4, 1);    

Serial.print(" Pin n°");
Serial.print(pin);
Serial.print(" à ");
Serial.println(Wire.read());

}

esclave :

#include <Wire.h> 

#define READ_PIN 0       //j'ai ajouter ceci sinon erreur indéfini variable

int pinToSend =0;  //j'ai ajouter ceci sinon erreur indéfini variable 

int buttonState = 0;
int buttonState2 = 0;

void setup()
{
Wire.begin(4);
//Wire.onReceive(receiveEvent); 
Wire.onRequest(requestEvent); /
Serial.begin(9600); 

pinMode(L1, OUTPUT); 
pinMode(L2, OUTPUT);
pinMode(bouton1, INPUT);
pinMode(bouton2, INPUT);
}

void loop()
{
delay(100);
}



void receiveEvent() {

byte x=Wire.read();
byte pin=Wire.read();

if(x==READ_PIN)  pinToSend=pin;

else digitalWrite(pin,Wire.read());

}

void requestEvent()

{
  
    Wire.write(digitalRead(pinToSend));
  

}

#define READ_PIN 0

int pinToSend =0;

j'ai ete obliger d'ajouter ceci car sinon indefini variable
par contre sur le moniteur serie du maitre je n'ai rien page vide

meme quant j'appui sur un des 2 bouton "de l'esclave"

Un peu normal si t'appelle jamais les fonctions ...

je viens de tester :

printState(5); // pour que sa me donne l'etat de l'inter pin 5 mais sa me met toujours :pin n=5 a 1 meme quant j'appui sur l'inter

setPin(3,HIGH); et la de je demande a la pin 3 de passer a HIGH sa ne marche pas non plus

Code complet ...

maitre :

#include <Wire.h>
#define SET_PIN 1
#define READ_PIN 0
const int L3 = 3;
void setup()
{
Wire.begin(); 
pinMode(L3, OUTPUT);
Serial.begin(9600); 
}

void loop()
{

printState(4);
printState(6);

 delay(100);

setPin(3,HIGH);
setPin(2,HIGH);
}

void setPin(int pin,byte state) {

Wire.beginTransmission(4); 
Wire.write(SET_PIN);  
Wire.write(pin);  
Wire.write(state); 
Wire.endTransmission(); 

}

void printState(int pin) {

Wire.beginTransmission(4); 
Wire.write(READ_PIN);  
Wire.write(pin);  
Wire.endTransmission(); 

Wire.requestFrom(4, 1);    

Serial.print(" Pin n=");
Serial.print(pin);
Serial.print(" à ");
Serial.println(Wire.read());

}

esclave :

#include <Wire.h> 

#define READ_PIN 0       //j'ai ajouter ceci sinon erreur indéfini variable

//int pinToSend =0;  //j'ai ajouter ceci sinon erreur indéfini variable 
const int bouton1 = 4;
const int bouton2 = 5;
int buttonState = 0;
int buttonState2 = 0;

void setup()
{
Wire.begin(4);
//Wire.onReceive(receiveEvent); 
Wire.onRequest(requestEvent); 
Serial.begin(9600); 

//pinMode(L1, OUTPUT); 
//pinMode(L2, OUTPUT);
pinMode(bouton1, INPUT);
pinMode(bouton2, INPUT);
}

void loop()
{
delay(100);

}



void receiveEvent() {

byte x=Wire.read();
byte pin=Wire.read();

if(x==READ_PIN)  pinToSend=pin;

else digitalWrite(pin,Wire.read());

}

void requestEvent()

{
  
    Wire.write(digitalRead(pinToSend));
  

}

Avec :

//Wire.onReceive(receiveEvent);

Comment veux-tu que ça fonctionne ?! Tu n'appelles jamais la routine qui pilote tout quand un message arrive du maitre.

quant j active cette ligne j'ai cette erreur
Arduino : 1.6.4 (Windows 8.1), Carte : "Arduino Uno"

Les options de compilation ont été modifiées, tout sera recompilé

Utilisation de la bibliothèque Wire prise dans le dossier : C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire

C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10604 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire C:\Users\jonathan\AppData\Local\Temp\build5095899778734670518.tmp\slave.cpp -o C:\Users\jonathan\AppData\Local\Temp\build5095899778734670518.tmp\slave.cpp.o

slave.ino: In function 'void setup()':
slave.ino:14:28: error: invalid conversion from 'void ()()' to 'void ()(int)' [-fpermissive]
In file included from slave.ino:1:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:67:10: error: initializing argument 1 of 'void TwoWire::onReceive(void ()(int))' [-fpermissive]
void onReceive( void (
)(int) );
^
slave.ino: In function 'void receiveEvent()':
slave.ino:37:18: error: 'pinToSend' was not declared in this scope
slave.ino: In function 'void requestEvent()':
slave.ino:47:28: error: 'pinToSend' was not declared in this scope
invalid conversion from 'void ()()' to 'void ()(int)' [-fpermissive]

Bin oui encore une ligne qu'il faut décommenté :

//int pinToSend =0;

meme avec sa:

#include <Wire.h> 

#define READ_PIN 0       //j'ai ajouter ceci sinon erreur indéfini variable
int pinToSend =0;  //j'ai ajouter ceci sinon erreur indéfini variable 
const int bouton1 = 4;
const int bouton2 = 5;
int buttonState = 0;
int buttonState2 = 0;

void setup()
{
Wire.begin(4);
Wire.onReceive(receiveEvent); 
Wire.onRequest(requestEvent); 
Serial.begin(9600); 

//pinMode(L1, OUTPUT); 
//pinMode(L2, OUTPUT);
pinMode(bouton1, INPUT);
pinMode(bouton2, INPUT);
}

void loop()
{
delay(100);

}



void receiveEvent() {

byte x=Wire.read();
byte pin=Wire.read();

if(x==READ_PIN)  pinToSend=pin;

else digitalWrite(pin,Wire.read());

}

void requestEvent()

{
  
    Wire.write(digitalRead(pinToSend));
  

}

j'ai un message d'erreur :

Arduino : 1.6.4 (Windows 8.1), Carte : "Arduino Uno"

Utilisation de la bibliothèque Wire prise dans le dossier : C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire

C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10604 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire C:\Users\jonathan\AppData\Local\Temp\build5095899778734670518.tmp\slave.cpp -o C:\Users\jonathan\AppData\Local\Temp\build5095899778734670518.tmp\slave.cpp.o

slave.ino: In function 'void setup()':
slave.ino:13:28: error: invalid conversion from 'void ()()' to 'void ()(int)' [-fpermissive]
In file included from slave.ino:1:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire/Wire.h:67:10: error: initializing argument 1 of 'void TwoWire::onReceive(void ()(int))' [-fpermissive]
void onReceive( void (
)(int) );
^
invalid conversion from 'void ()()' to 'void ()(int)' [-fpermissive]

Corrigé :

#include <Wire.h> 

#define READ_PIN 0       //j'ai ajouter ceci sinon erreur indéfini variable
int pinToSend =0;  //j'ai ajouter ceci sinon erreur indéfini variable 
const int bouton1 = 4;
const int bouton2 = 5;
int buttonState = 0;
int buttonState2 = 0;

void setup()
{
Wire.begin(4);
Wire.onReceive(receiveEvent); 
Wire.onRequest(requestEvent); 
Serial.begin(9600); 

//pinMode(L1, OUTPUT); 
//pinMode(L2, OUTPUT);
pinMode(bouton1, INPUT);
pinMode(bouton2, INPUT);
}

void loop()
{
delay(100);

}



void receiveEvent(int howMany) {

byte x=Wire.read();
byte pin=Wire.read();

if(x==READ_PIN)  pinToSend=pin;

else digitalWrite(pin,Wire.read());

}

void requestEvent()

{
  
    Wire.write(digitalRead(pinToSend));
  

}

je te remercie énormément de ton aide

(1)
est ce normal que la led s'eclaire legerement " car
avec mon code " hyper brouillon" que j'avait au debut sa eclairer a fond et la non ?

(2)
pour interagir sur un état de pin sur le maître est ce bien la bonne procédure :

void loop (){

if (printState(6) == 1){
digitalWrite(L3, HIGH);
}
else{
digitalWrite(L3, LOW);
}
delay(500);
}