If I remove the transmission code from slave this works properly but I need to transmit from slave.
Here is my master code
#include <Wire.h>
void setup() {
Wire.begin(3);
Wire.onReceive(receiveEvent);
}
byte x = 0;
void loop() {
Wire.beginTransmission(9);
Wire.write("s");
Wire.write(x);
Wire.endTransmission();
x++;
delay(500);
}
void receiveEvent(int howMany) {
if(Wire.available()){
int x = Wire.read();
Serial.println(x);
}
}
Here is my slave code:
#include <Wire.h>
void setup() {
Wire.begin(9); // join i2c bus with address #9
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
}
void loop() {
delay(100);
}
void receiveEvent(int howMany) {
if(Wire.available()){
char c = Wire.read();
Serial.print(c);
if(c == 's'){
int x = Wire.read();
Serial.println(x);
//transmit to master
Wire.beginTransmission(3);
Wire.write(1);
Wire.endTransmission();
} else {
Wire.read();
}
}
}
Is it possible not to use Wire.onRequest(requestCallback); to send data to master? Kindly help.
-
1When a sketch calls Wire.begin() and passes a number, it has nominated itself as a slave on the bus. So you appear to have two slaves. Normally one would have one master and one slave.James Cameron– James Cameron2014年06月23日 08:44:37 +00:00Commented Jun 23, 2014 at 8:44
-
What you seem to want is a combination of the Arduino Wire Tutorial arduino.cc/en/Tutorial/MasterReader and arduino.cc/en/Tutorial/MasterWriter do you agree?James Cameron– James Cameron2014年06月23日 08:50:22 +00:00Commented Jun 23, 2014 at 8:50
-
i had a look but not able to implement it properly any suggestion ? if i give 2 wire.write the master is not reading it properlysrinivas– srinivas2014年06月23日 09:21:27 +00:00Commented Jun 23, 2014 at 9:21
-
I don't know what you mean, sorry.James Cameron– James Cameron2014年06月23日 09:37:38 +00:00Commented Jun 23, 2014 at 9:37
-
the Wire.requestFrom has only one wire.write i need multiple wire.write which is not supported so is there any workarounds ?srinivas– srinivas2014年06月23日 14:30:10 +00:00Commented Jun 23, 2014 at 14:30
3 Answers 3
To join the bus as a master you cannot supply a 7-Bit slave address so your code has two slaves.
Below you will find 2 sketches that successfully sends data to a slave. I would suggest you start looking at the I2C protocol and understand there are 4 Modes:
- Master->Transmitter
- Master->Receiver
- Slave->Transmitter
- Slave->Receiver
All communications regardless of how the data is transferred requires a master. It's the master that controls the clock pulses, thats why its always the master that initiates the communcation.
The MasterReader/MasterWriter tutorials on the arduino forum should now possibly start to make a little more sense when understanding those modes.
This code shows how a master sends data to a slave, and then how it requests data from the slave. If we look at this code from the master point-of-view, you can see it essentially says, send this byte to the client (m->t & s->r), then request data from the slave (m->r,s->t)
Master Code
#include <Wire.h>
#define SLAVE_ADDRESS 0x60
void setup()
{
Wire.begin();
randomSeed(analogRead(3));
Serial.begin(9600);
}
byte x = 0;
void loop()
{
x = random(0,255);
Serial.print("Sent: ");
Serial.print(x, HEX);
Serial.print("\n");
Wire.beginTransmission(0x60);
Wire.write(x);
Wire.endTransmission();
delay(500);
Serial.println("Requesting Data");
Wire.requestFrom(SLAVE_ADDRESS, 1);
int bytes = Wire.available();
Serial.print("Slave sent ");
Serial.print(bytes);
Serial.print(" of information\n");
for(int i = 0; i< bytes; i++)
{
x = Wire.read();
Serial.print("Slave Sent: ");
Serial.print(x, HEX);
Serial.print("\n");
}
delay(500);
}
Slave Code
#include <Wire.h>
#define SLAVE_ADDRESS 0x60
byte x = 0x00;
void setup()
{
Wire.begin(SLAVE_ADDRESS);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
Serial.begin(9600);
}
void loop()
{
delay(100);
}
void requestEvent()
{
Serial.print("Request from Master. Sending: ");
Serial.print(x, HEX);
Serial.print("\n");
Wire.write(x);
}
void receiveEvent(int bytes)
{
if(Wire.available() != 0)
{
for(int i = 0; i< bytes; i++)
{
x = Wire.read();
Serial.print("Received: ");
Serial.print(x, HEX);
Serial.print("\n");
}
}
}
-
On master you could scan the address range for connected device. This would be a proper approach.wajatimur– wajatimur2015年02月04日 17:56:08 +00:00Commented Feb 4, 2015 at 17:56
-
In both of your event handlers: Don't do serial prints inside an ISR. It may work until the serial buffer fills up, then it will hang.2015年07月22日 23:49:15 +00:00Commented Jul 22, 2015 at 23:49
-
1You don't need to test
if(Wire.available() != 0)
because thebytes
variable has the number of bytes you received. If anything, test ifbytes > 0
however I presume that a receive event would have at least one byte.2015年07月22日 23:50:31 +00:00Commented Jul 22, 2015 at 23:50
I went through this problem recently. Your slave needs two functions: one for sending and the other for receiving data.
// function: what to do when asked for data
void requestEvent() {
Wire.write(t);
}
// what to do when receiving data from master
void receiveEvent(int howMany)
{Val = Wire.read();}
Here is a code that works both ways of i2c communication in a single code
Sending and receiving different types of data via I2C in Arduino
You had:
void receiveEvent(int howMany) { { if(Wire.available()){ char c = Wire.read(); Serial.print(c); if(c == 's'){ int x = Wire.read(); Serial.println(x); //transmit to master Wire.beginTransmission(3); Wire.write(1); Wire.endTransmission(); }else{ Wire.read(); } } }
There are a number of problems with your slave code.
- Don't do Serial prints in an ISR (interrupt service routine)
- Don't do beginTransmission / endTransmission in a receive event.
- Don't do any writes
- To send data back use a requestEvent not a receiveEvent.
Better would be:
// add in setup()
Wire.onRequest (requestEvent); // interrupt handler for when data is wanted
...
volatile byte what;
void receiveEvent(int howMany)
{
if (howMany < 2)
return;
char c = Wire.read ();
if (c != 's')
return;
what = Wire.read (); // remember what we got
} // end of receiveEvent
void requestEvent()
{
Wire.write (1); // return a response
} // end of requestEvent
the Wire.requestFrom has only one Wire.write. I need multiple Wire.write which is not supported so are there any workarounds?
Batch up the response and do one write:
void requestEvent ()
{
byte buf [4] = { 1, 2, 3, 4 };
Wire.write (buf, sizeof buf); // send response
} // end of requestEvent
Reference
There are a lot of examples at I2C - Two-Wire Peripheral Interface - for Arduino