mgb
September 28, 2026, 2:18pm
1
I have a simple master/slave with I2C to link 2 Nanos. The problem is that the slave sends the byte 100000 but the master receives 11111111
The 2 nanos are each connected to separate laptops which provide the power through the USB connectors
The master code is
#include <Wire.h>
byte ind_stalk_status;
long slave_poll_time = 0;
#define IND_STALK_ADDR 9
void setup(void) {
Serial.begin(9600);
Wire.begin();
Wire.setWireTimeout(3000, true);
}
void loop() {
if (millis() - slave_poll_time > 1500) {
slave_poll_callback();
slave_poll_time = millis();
}
}
void slave_poll_callback() {
Wire.requestFrom(IND_STALK_ADDR, 1);
byte ind_stalk_status = Wire.read(); // receive a byte
Serial.print(F("slave_poll_callback: "));
Serial.println(ind_stalk_status, BIN); // print the byte
}
This prints slave_poll_callback: 11111111 on each poll
Slave code
#include <Wire.h>
void setup() {
Serial.begin(9600);
Wire.begin(9);
Wire.setWireTimeout(3000, true);
Wire.onRequest(requestEventReceived);
}
void requestEventReceived(int bytes) {
byte ind_status;
bitWrite(ind_status, 5, 1);
Serial.print(F("requestEventReceived "));
Serial.print(F("ind_status "));
Serial.println(ind_status, BIN);
Serial.flush();
Wire.write(ind_status);
}
This prints requestEventReceived ind_status 100000 on each request
That value suggests a very basic communications error. Be sure to check function return values for error status, keeping in mind that the Arduino Wire library is not very robust.
Don't you mean
byte ind_status = 0;
Edit: You aren't sending anything to the slave.
The slave is going to send one byte,.
mgb
September 28, 2026, 2:47pm
4
I assume that byte ind_status; will set the byte to 0 and the bitWrite(ind_status, 5, 1) will change the byte to 100000
mgb
September 28, 2026, 2:49pm
5
Doesn’t the fact that the return is 11111111 mean that the link returned a byte?
I would not assume that. Set it to zero and see if it makes a difference.
Is the slave return the same every request?
mgb
September 28, 2026, 2:51pm
7
Thanks, the print shows 100000 so the byte is being set correctly
Here is my slave
#include <Wire.h>
byte array[8] = {2,4,6,8,10,12,14,16};
volatile byte regReq = 0;
volatile byte* rtnPtr;
void setup()
{
Wire.begin(13);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
}
void loop()
{
}
void receiveEvent(int byteCount)
{
regReq = Wire.read();
}
void requestEvent()
{
rtnPtr = &array[regReq*2];
Wire.write((byte*)rtnPtr,2);
rtnPtr += 2;
}
Here is my master
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin(); // join i2c bus (address optional for master)
}
byte x = 0;
int failCount = 0;
void loop() {
Wire.beginTransmission(13); // transmit to device #13
Wire.write(x); // sends one byte
if(Wire.endTransmission() != 0)
Serial.println("Write failed");
delayMicroseconds(10);
if(Wire.requestFrom(13, 2) == 2) { // request 2 bytes from slave device #13
while(Wire.available()) // slave may send less than requested
{
char c = Wire.read(); // receive a byte as character
Serial.print(c,DEC); // print the character
Serial.print(" ");
}
Serial.print(failCount);
Serial.println();
}
else {
Serial.println(F("Fail"));
failCount++;
}
x++;
if(x > 3) x = 0;
delay(500);
}
1. Let us say that the I2C-Master requests the I2C-Slave to send 1-byte data (0x23) at 1-sec intervals.
2. Check that your NANO-Mater and NANO-Slave are connected as per Fig-1:
Figure-1:
3. Upload the following sketches.
Master Sketch:
#include <Wire.h>
#define slaveAddr 0x09
void setup() {
Serial.begin(9600);
Wire.begin();
//------------
Wire.beginTransmission(slaveAddr);
byte busStatus = Wire.endTransmission();
if (busStatus != 0) {
Serial.println("Slave is not found!");
while (true)
;
}
Serial.println("Slave is found.");
}
void loop() {
Wire.requestFrom(slaveAddr, 1);
byte data = Wire.read();
Serial.println(data, HEX); //shows: 23
delay(1000);
}
Slave Sketch:
#include <Wire.h>
#define slaveAddr 0x09
void setup() {
Serial.begin(9600);
Wire.begin(slaveAddr);
//------------
Wire.onRequest(sendEvent);
}
void loop() {
}
void sendEvent() {
Wire.write(0x23);
}
5. Check that SM1 (Serial Monitor 1) shows 23 at 1-sec intervals.
6. Replace 0x23 with 0xFF (11111111) and upload the Slave sketch.
7. Check that SM1 shows FF (11111111).
mgb
September 28, 2026, 4:21pm
10
Thanks, the significant difference is that you are using Wire.available(), I will that a try
mgb
September 28, 2026, 4:24pm
11
I don’t have resisters on the I2C lines, I will give them a try
You must need pull-up resistors on the I2C bus as the lines are open-drain.
kmin
September 28, 2026, 4:46pm
13
GolamMostafa:
lines are open-drain.
I agree with external pullups, however doesn't Wire.begin activate internal ones?
Internal pull-up is 20k - 50k, which offers very weak pull-up!
Adding external 2x4.7 k pull-up resistors from SDA and SCL to VCC provides enough current to ensure sharp, clean voltage transitions.
kmin
September 28, 2026, 5:47pm
15
I have never tried without external pullups.
Question was if internals are automatically used or lines are open-drain.
I always run the i2c_scanner sketch to check the connection.
I use 5k pullups when I use a SAMD21 as the i2c slave.
No, it just suggests that the input pullups are working on the receive end. There are several tested, functional examples of Arduino-to-Arduino communication via I2C posted on the web. Try one of those before writing your own code.
This post on Wire has helpful explanations, suggestions and warnings, e.g.
The function Wire.requestFrom() reads data. After it is finished, the received data is in a buffer (inside the Wire library). That data can be read with Wire.read() . The Wire.available() tells how many bytes are still in that buffer.
When there was a problem during the I2C bus activity, the received bytes up to that point are not reliable. With the Arduino Wire library it is not even possible to know if there are any reliable bytes before the bus error did happen. It is therefor better to first check for errors and if there are no errors, then read all the bytes.
Checking for errors might not be needed, see the Check for bus errors ? page.
Finally, "separate laptops", if both powered from the AC line, can lead to noise problems with ground loops. Test using battery power only.
mgb
September 29, 2026, 7:53am
18
I have 5 Nanos daisy chained together for the I2C bus. I'm not hot on the electronics side but will pull up resistors be required on only one Nano as the whole line will be pulled up
mgb
September 29, 2026, 8:54am
19
Solved: Many thanks to all that helped, a pull-up resistor on the clock pin A5 did the trick. Originally I added a resistor to both A4 and A5 and the link wouldn’t work, as soon as I removed the one from A4, it started transmitting successfully
mgb:
Solved:
This is not a solution!
You must be placing pull-up resistors for both lines of the I2C bus as per Fig-1 of post #9 along with common GND line connected between the NANOs.
Can you confirm to me that the sketches in post #9 work for you? If they work, then that is the solution.