i2c Wire communication between MEGA and TINY AVRs

Hi there!

Is it possible to communicate between Mega and Tiny AVRs via i2c?

I know there is the Wire library for Megas but Tinies dont have
hardware i2c ports. I was experimenting with the TinyWire library but
this library generates an error when running on Megas.

I would like to build a node network (multiple tiny avrs) communicating with a
base station (one Mega).

Thanks in advance!

Attiny2313 hardware supports I2C.
So does Attiny 24/44/84 series.
So does Attiny 25/45/85.
Which Attiny where you thinking of?
Is there no library for those?

Thanks for your reply!
I thought the tinies can only use software emulated i2c?

I was experimenting with this library (TinyWireS+M):
http://playground.arduino.cc/Code/USIi2c

I got the library working for :
ATtiny85 <-> ATtiny85

But not in this setup:
ATtiny85 <-> ATMega328 (compiler error)

The ATtiny2313 isnt an option for me because this chip only has digital
pins right? I need some analog pins too for sensor readings.

The standart "Wire" library does not support the tinies (got it working for ATmega328 <-> ATmega8).

No ideas how to let Attinies talk to Atmegas? :frowning:

asuryan:
No ideas how to let Attinies talk to Atmegas? :frowning:

You say you managed to get Tiny85 talking to Tiny85 using the master & slave libraries you linked to so one can assume the wiring is correct (I was going to ask what pins your using).

When you try talking Mega to Tiny are you using Wire library or the TinyWireM on the Mega and what pins are you using?

The playground link quotes...

Be sure to use pullups! (4.7K on 5V). I2C with these libs is not as forgiving as the Wire lib. (Maybe the internal pullups are not set.)

The TWI library used by Wire.h sets pullups on the SCL/SDA pins and also the usiTwiSlave also sets pullups on but they might not be enough?

Thanks for your reply!

Unforunately the problem exists allready when compiling the code (TinyWire library) for the mega (on tinies the code compiles without problems):

/Users/Marius/Documents/EigeneProjekte/Programming/Arduino/libraries/TinyWireM/USI_TWI_Master.cpp: In function 'void USI_TWI_Master_Initialise()':
/Users/Marius/Documents/EigeneProjekte/Programming/Arduino/libraries/TinyWireM/USI_TWI_Master.cpp:48:3: error: 'PORT_USI' was not declared in this scope
   PORT_USI |= (1<<PIN_USI_SDA);           // Enable pullup on SDA, to set high as released state.
   ^
/Users/Marius/Documents/EigeneProjekte/Programming/Arduino/libraries/TinyWireM/USI_TWI_Master.cpp:48:19: error: 'PIN_USI_SDA' was not declared in this scope
   PORT_USI |= (1<<PIN_USI_SDA);           // Enable pullup on SDA, to set high as released state.
                   ^
/Users/Marius/Documents/EigeneProjekte/Programming/Arduino/libraries/TinyWireM/USI_TWI_Master.cpp:49:19: error: 'PIN_USI_SCL' was not declared in this scope
   PORT_USI |= (1<<PIN_USI_SCL);           // Enable pullup on SCL, to set high as released state.
                   ^
/Users/Marius/Documents/EigeneProjekte/Programming/Arduino/libraries/TinyWireM/USI_TWI_Master.cpp:51:3: error: 'DDR_USI' was not declared in this scope
   DDR_USI  |= (1<<PIN_USI_SCL);           // Enable SCL as output.
   ^
/Users/Marius/Documents/EigeneProjekte/Programming/Arduino/libraries/TinyWireM/USI_TWI_Master.cpp:54:3: error: 'USIDR' was not declared in this scope
   USIDR    =  0xFF;                       

//......

/Users/Marius/Documents/EigeneProjekte/Programming/Arduino/libraries/TinyWireM/USI_TWI_Master.cpp:324:9: error: 'USISR' was not declared in this scope
   if( !(USISR & (1<<USIPF)) )
         ^
/Users/Marius/Documents/EigeneProjekte/Programming/Arduino/libraries/TinyWireM/USI_TWI_Master.cpp:324:21: error: 'USIPF' was not declared in this scope
   if( !(USISR & (1<<USIPF)) )
                     ^
Fehler beim Kompilieren.

I shortend the error output because this would exceed the maximum post length.
It seems that the library requests stuff that is not available on the mega? :frowning:

Trying to compile the standart Wire library (compiles without problems on the mega) on tinies gives me this error:

Arduino: 1.6.4 (Mac OS X), Platine: "ATtiny, ATtiny85, 8 MHz (internal)"

/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/libraries/Wire/Wire.cpp: In member function 'void TwoWire::setClock(uint32_t)':
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/libraries/Wire/Wire.cpp:80:3: error: 'TWBR' was not declared in this scope
   TWBR = ((F_CPU / frequency) - 16) / 2;
   ^
Fehler beim Kompilieren.

So both libraries seem not to be "cross"-plattform compatible out of the box... :frowning:

Is there a cross plattform alternative or do I have to write my own inter-chip-communication library? O.O

I think you used the TinyWire slave library on the Tiny but use the Wire library on the Mega. If the TinyWire library properly emulates/supports the I2C standard then it should work with any other master device using I2C to talk to it. In this case it will be a Mega that needs Wire.h to support I2C.

Hey Riva thanks for your reply!

That sounds super logical to me! :slight_smile:

I tried what you suggestet but it seems there is still something wrong either with my code or wiring. :frowning:

Here is the code from the master (Arduino UNO):

#include <Wire.h>

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  pinMode(13,OUTPUT);
  blinky(200,13,5);
}

void loop()
{
  Serial.println("Hello");
  Wire.requestFrom(20, 2);  
  while (Wire.available())
  {
    byte c = Wire.read();
    Serial.print(c);  
    digitalWrite(13,HIGH);
    delay(500);
    digitalWrite(13,LOW);
    delay(500);
  }
  delay(500);
}

void blinky(int theSpeed, int port, int count)
{
  for(int i=0;i<count;i++)
  {
    digitalWrite(port,LOW);
    delay(theSpeed);
    digitalWrite(port,HIGH);
    delay(theSpeed);
    digitalWrite(port,LOW);
  }
}

Here is the code for the slave (ATtiny85):

#include <TinyWireS.h>
#include <usiTwiSlave.h>

void setup()
{
  pinMode(4,OUTPUT);
  TinyWireS.begin(20);
  blinky(50,4,10);
}

void loop()
{
  if(TinyWireS.available())
  {
    byte c = 9;
    TinyWireS.send(c);
    blinky(250,4,5);
  }
}

void blinky(int theSpeed, int port, int count)
{
  for(int i=0;i<count;i++)
  {
    digitalWrite(port,LOW);
    delay(theSpeed);
    digitalWrite(port,HIGH);
    delay(theSpeed);
    digitalWrite(port,LOW);
  }
}

Both compile without errors.

My wiring is attached as an image below.

The expecet output would be in the serial monitor:
Hello
9
Hello
9
Hello
9
...

But I only get:
Hello
Hello
Hello
Hello
...

What am Im doing wrong? :frowning: Any ideas? :frowning:

asuryan:
Here is the code from the master (Arduino UNO):

#include <Wire.h>

void loop()
{
 Serial.println("Hello");
 Wire.requestFrom(20, 2);  
 while (Wire.available())
 {
   byte c = Wire.read();
   Serial.print(c);  
   digitalWrite(13,HIGH);
   delay(500);
   digitalWrite(13,LOW);
   delay(500);
 }
 delay(500);
}

Here is the code for the slave (ATtiny85):

[code]#include <TinyWireS.h>
#include <usiTwiSlave.h>

void setup()
{
 pinMode(4,OUTPUT);
 TinyWireS.begin(20);
 blinky(50,4,10);
}

void loop()
{
 if(TinyWireS.available())
 {
   byte c = 9;
   TinyWireS.send(c);
   blinky(250,4,5);
 }

}




Both compile without errors.

Where is the TinyWires.onRequest(handler)?

Your tiny Slave code needs to be something like this:

void sendRequested(){

uint8_t data[25];
uint8_t datalen=25;
// fill data buffer with request info first

TinyWireS.send(data,datalen);
}


void setup(){
TinyWireS.begin(20);
TinyWireS.onRequest(sendRequested);

////
}

The code in loop() is bogus. The sendRequested() is the response routine. Loop doesn't interact with tinyWire.

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.

First problem I can see is you have the SCL/SDA wires crossed between the UNO & Tiny. From your picture the green wire should be on A4 of the UNO and yellow on A5.

I would also try using the example that comes with the TinyWireS library as your example does not pull the request off the I2C bus and I don't know if this will cause problems.

The master is requesting 2 bytes of data but I'm not sure the slave will actually send 2 bytes in reply.

Thanks guys!

  1. I switched the wires A4 (Uno) -> 5 (Tiny) and A5 (Uno) -> 7 (Tiny)
    The thing is I now get only one "Hello" and then nothing anymore. If I remove the wires the "Hello" prints again. It seems the Uno crashes or hangs?! :o

  2. Unfortunately the TinyWire Library does not have an onRequest handler. From the docs (Arduino Playground - HomePage):

The slave lib is also missing the "onReceive" and "onRequest" functions - however it is still usable.

  1. You re right: Im requesting 2 bytes... I changed that to one but still no luck :frowning:

I would also try using the example that comes with the TinyWireS library as your example does not pull the request off the I2C bus and I don't know if this will cause problems.

Try doing the "TinyWireS.receive();" else proper handshaking will not happen and the master may lock up waiting for a reply.

void loop(){
  byte byteRcvd = 0;
  if (TinyWireS.available()){           // got I2C input!
    byteRcvd = TinyWireS.receive();     // get the byte from master
    Blink(LED1_PIN,byteRcvd);           // master must wait for this to finish before calling Wire.requestFrom
    byteRcvd += 10;                     // add 10 to what's received
    TinyWireS.send(byteRcvd);           // send it back to master

    Blink(LED2_PIN,1);                  // show we transmitted
  }
}

asuryan:
2. Unfortunately the TinyWire Library does not have an onRequest handler. From the docs (Arduino Playground - HomePage):

The latest version of the library does support onRequest & onReceive but the version your using should work okay as your polling the .available().