1

I want to make my Attiny85 and my Arduino UNO communicate together with I2C protocol. Since Attiny do not support Wire library, I use TinyWire by lucullusTheOnly and Wire on the Uno.

The Attiny is sending data as the master to the Uno, the slave.

Here is my code:

Master

#include <TinyWire.h>

byte slave_address = 10;


void setup() {
    // config TinyWire library for I2C master functionality
    TinyWire.begin();
}

void loop() {
    TinyWire.beginTransmission(slave_address);
    TinyWire.send('c');
    // endTransmission sends the bytes in the buffer to the slave and returns 0 if there was no error
    TinyWire.endTransmission();
    delay(500);
}

Slave

#include <Wire.h>

void setup() {
  Wire.begin(10);                // join i2c bus with address #10
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
  delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  while (1 < Wire.available()) { // loop through all but the last
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}

I connect the pin like this :

Arduino --> Attiny
SCL ---- PIN 7
SDA ---- PIN 5

I try to pull-up the clock and data line with 2.2k resistors but nothing happened, I receive nothing on the Uno from the Attiny. Any idea ? Thanks !

2
  • 1
    Also asked at: forum.arduino.cc/index.php?topic=524760 If you're going to do that then please be considerate enough to add links to the other places you cross posted. This will let us avoid wasting time due to duplicate effort and also help others who have the same questions and find your post to discover all the relevant information.
    – per1234
    Commented Jan 25, 2018 at 8:47
  • As per Stackexchange rules, I don't think he is obligated to post links to other forums where he has asked for an answer. It's his choice. Nevertheless, thanks for posting the link to the forums, it helps other readers.
    – dsignr
    Commented Nov 26, 2018 at 14:37

2 Answers 2

1

The pure master functionality of the TinyWire library is currently buggy. As a work around you can initiate the library on the ATTiny also as a slave with an address. When the endTransmission() function is called, the library switches temporarily to master mode for sending the bytes. I've tested this with your code in my own setup and it works. (Be sure, that the frequency in the ATTiny is set right. I tested the library only for 8MHz. For my own ATTiny's I had to do an extra step and set the correct fuses with avrdude)

I think the pure master part is blocking itself after the first transmission. I will add an issue in the github project. Maybe I can fix this in some time.

Chrisl aka lucullusTheOnly

EDIT: I had to think about this and looked into the library. The problem was found easily. In twi.cpp there is a NOISE_TESTING define block in the master send/receive function, which is constantly triggering error #6 (unexpected stop condition). In slave mode this doesn't happen, because directly before sending as a master it calls the master init function, which clears all USI flags, including the stop condition flag, that is polled in the send/receive function.

I have deactivated the NOISE_TESTING in the github project. If you don't want to download the current version, you can just open twi.h and comment the definition of NOISE_TESTING.

1
  • I finally move to the Serial library but I will test your new code soon! Commented Jan 29, 2018 at 19:29
0

I have the same issue even though I have the latest Github version with the NOISE_TESTING define block disabled.

I believe it has something to do with the line 359 in TWI.cpp where the stop condition isn't issued if a NACK happens:

      if( temp_result.result & (1<<TWI_NACK_BIT) ) 
  {
    if ( USI_TWI_state.addressMode )
      USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;
    else
      USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
    return (FALSE);
  }

I think it should be :

      if( temp_result.result & (1<<TWI_NACK_BIT) )
  {
    if ( USI_TWI_state.addressMode )
      USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;
    else
      USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
    USI_TWI_Master_Stop();
    return (FALSE);
  }

I tried it on ISIS in pure master only and it worked. I don't know if this is a viable solution or if it will cause any conflict with how the rest of the lib works.

Your Answer

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

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