0

I am developing a multi-master scenario sketch with the https://github.com/rambo/I2C library, because this library will handle multi-master data collisions.

I created a setup with two Arduino nano's which act both as master and slave.
My sketch works as long as I use only one master. Sending data from one Arduino to the other works fine. The other receives the data.

But when I sequentially try to send data from the second Arduino to the first, I get an error (32). After that even sending data from the initial Arduino results in error 32.

This is the used sketch for both the Arduino's. The only difference is that I switch the values of rel_address and own_address when programming the seconds Arduino.

Sending data is done by pressing a button on pin 2 (switchPin)

/**
   atme328 = ATmega328
   SDA --> Pin A4
   SCL --> Pin A5
*/
#include <I2C.h>
#include <Wire.h>

int switchPin = 2;
int relayOnPin = 3;
int relayOffPin = 4;

uint8_t broadcast_address = 0;
uint8_t own_address = 11; // CHANGE FOR EVERY MODULE!!
// rel_address = address of relay to switch; SET to own_address if relay is connected to this chip!
uint8_t rel_address = 10; // CHANGE FOR EVERY MODULE!! SET to own_address if relay is connected to this chip!
uint8_t rpi_address = 1;

unsigned long counter = 0;

void setup() {

   Serial.begin(9600);
   pinMode(switchPin, INPUT_PULLUP);

   pinMode(relayOnPin, OUTPUT);
   pinMode(relayOffPin, OUTPUT);
   // start condition
   digitalWrite(relayOnPin, HIGH);
   digitalWrite(relayOffPin, LOW);

   I2c.begin();
   I2c.timeOut(50);
   // I2c.pullup(true); // done by external 4.7kOhm resistors

   // config Wire library for I2C slave functionality
   Wire.begin( own_address );

   TWAR = (own_address << 1) | 1;  // enable broadcasts to be received!

   // set slave receive callback
   Wire.onReceive( onI2CReceive );

}

void loop() {
   counter = counter + 1;
   if (counter == 20000) {
      digitalWrite(relayOnPin, LOW);
      digitalWrite(relayOffPin, LOW);
   }
   if ( digitalRead(switchPin) == LOW ) {
      sendCmd('d', rel_address); // send command to remote relay
   }
}

void sendCmd(uint8_t cmd, uint8_t address) {
   uint8_t status = I2c.write(address, cmd); //configure device for continuous mode
   if (status > 0) {
      // error codes at https://github.com/rambo/I2C/blob/master/I2C.cpp
      Serial.print(status, DEC);
      Serial.print('!');
      digitalWrite(relayOffPin, HIGH);
      delay(50);
   } else {
      digitalWrite(relayOnPin, HIGH);
      Serial.print('.');
   }
   counter = 0;
}

void onI2CReceive(int howMany) {
   // loops, until all received bytes are read
   while (Wire.available() > 0) {
      digitalWrite(relayOffPin, HIGH);
      Serial.write(Wire.read());
   }
   counter = 0;
}

What do I need to do to be able to send from two units using this library? Thanks!

5
  • 1
    Shouldn't you use only one I2C library?
    – Juraj
    Feb 23, 2018 at 10:39
  • the repeated starts support was added to Wire library some yeas ago, if this is the reason you use the I2C library
    – Juraj
    Feb 23, 2018 at 10:47
  • @Juraj the I2C library only supports master operations. I found some dedicated master / dedicated slave example of the I2C library and they also use the Wire library for the slave (github.com/Scott216/I2C-Examples)
    – mvermand
    Feb 23, 2018 at 11:07
  • I use the I2C library to overcome the hanging of the sketch on master send collision. If I use the Wire library, the sketch simply hangs on a collision. Something in the Wire library so it seems...
    – mvermand
    Feb 23, 2018 at 11:09
  • examples can use Wire for slave, but not in the same sketch. both libraries set the same I2C registers
    – Juraj
    Feb 23, 2018 at 14:08

2 Answers 2

1

You cannot use the I2C library and the Wire library at the same time. From the code I guess you wanted the Wire library to do the slaves job and the I2C library to implement the master. But since both libraries use the same hardware, this cannot be divided between them. Combining two libraries for the same hardware isn't that trivial. The I2C library only provides master functionality. So, to reach your goal, you would have to find a library, that provides both master and slave functionality while doing correct bus arbitration (which is the term for correctly handling master data collisions). Or you have to change one of the two libraries yourself, to provide the missing functionality.

And the error you get is defined in #define MT_SLA_NACK 0x20 in I2C.h (0x20 is equal to 32). This means, that you haven't got an acknowledgement from the slave you have addressed. This suggests, that in your current code only the master functionality is working. (But it may have another meaning considering the interaction of the two libraries on the same hardware)

0

I ended up removing the I2C library and using a modified version of Wire. I replaced the twi.h and twi.c libraries in C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility with those from http://liken.otsoa.net/pub/ntwi/. This implementation adds timeouts to the operations, which prevents a hang-up.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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