0

I'm trying to send data both ways between an Arduino Mega 2560 slave and 2 Arduino Nano Zero (ATSAMD21G).

This example is a simplified setup and code. There will be more masters along with passive slaves on the bus (LCD, EEPROM).

Code and results (txt files)

My code is working fine with one master only and the slave active on the bus (data is sent both ways every 2s). I however notice missing transfers to the masters when more than one master is active. The 2 masters to slave transfers are working properly (once the 2 masters are on, the data is received by the slave every 2s from each master).

Is this problem due to collision? How can I handle it?

  • 1
    Unless this is class work or just you exploring how I2C works, I would suggest you stick with 1 master and poll the other I2C slave devices. Otherwise read up on I2C. I think you can only have one master at a time and the method to switch who is the master is part of the I2C protocol. BTW, I know SPI requires more wires, but people generally have less problems getting SPI to work. – st2000 Feb 22 '17 at 2:17
  • 1
    The chip itself can detect collisions. I'm not sure if the Wire library fully implemented that. You would need to check the return value of every Wire.endTransmission and every Wire.requestFrom. I agree with st2000, it is better to stay out of trouble and have only one Master. Sometimes an extra interrupt signal is added to the I2C bus, to make it possible that a Slave can notifiy the Master that data is ready and waiting. – Jot Feb 22 '17 at 8:29
  • I saw quite a lot of people hit a wall with this on Arduinos. It would be great to have a solution to address it that's not a workaround with loss of functionality or extra wires. Having multiple masters that can communicate when they need to, with multiple slaves allows a lot of fun developments! The protocol and chips are supposed to handle collision but I read the wire library doesn't implement it. I'll check what I can do with Wire.endTransmission and Wire.requestFrom return values. – kb_ Feb 22 '17 at 11:01
  • Wire.requestFrom returns "byte : the number of bytes returned from the slave device". I guess these bytes can contain the real data or something random due to collision... Wire.endTransmission returns success or errors, so that should work (Master to slave was already working in my code without this check) Is there an improved version of the Wire library that handles this better? Otherwise I'm thinking of polling at a faster rate and add a CRC check, but that would add back and forth communications between masters and slave. – kb_ Feb 22 '17 at 11:01
0

notice missing transfers to the masters when more than one master is active.

Because you didn't provide a way for the master's to know of a transmission ISS in progress. Lack of conflict resolution. A problem with all multimeter transmission.

A simpler approach is for the slave to signal a transmission from the master. That can be done via a slave requestion pin from the slave to the master.

  • The I2C protocol handles multimaster, without this kind of workarounds. The communication library should do that too. I could add wires, but who has spare pins? – kb_ Feb 23 '17 at 21:40
0

The code had several issues leading to a constant flow of wrong data (with correct data in the middle) between the master that won the bus arbitration. This made it keep the bus too long and eventually give it away to the second master at a random time, with missed transfers from the second master in between. The second master was then behaving the same and so on.

receiveEvent, on the slave side, contained a millis if condition timer that made it time out. I moved the timer to the master side before calling Wire.requestFrom. Avoid slow code in receiveEvent!

receiveEvent, on the slave side, was also confusing real data with incoming requestEvent. I added an if statement to compare the receiveEvent data size with the expected size. Half of the data was wrong without this filter (this should ideally be handled in the Wire library)

These fixes solved the busy bus problem. I figured these out after asking question #35092

The bus speed also had to be reduced because 800 kHz was too fast for the Mega 2560 (but worked between 3 Nano).

The slave has to send the data destined to both masters to each of them because requestEvent can't tell which master is asking for data. The data is then filtered on each master to only keep the relevant information.

The data is now being transferred both ways between the 2 Nano masters and the Mega slave at the correct interval, without corrupt data.

fixed Slave code

fixed Master 1 code

fixed Master 2 code in the same repo (I'm limited to 2 links post)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.