I2C with Wire.h and TinyWireS.h Issues

Hey everyone!

I’m not new to programming, but I’m new to using I2C. Specifically, I have two boards that I’m trying to network together for a custom HID I’m working on. My problem isn’t the HID portion, as I’ve tested that alone, so I’ve gone to trouble-shooting the data transmission. The slave board is a DigiSpark ATTINY85, and the master is a MEGA 2560. I’ve tried to have it work as a slave reader/master writer configuration. The circuitry should be fine, but I’m including diagrams of everything. The issue I’m having is easy to identify: the slave is receiving the first data set, but it isn’t receiving any more.

Please ignore all the weird wiring to the header at the bottom. It’s going to an old gameport joy-stick right now.

As for the code, here’s the master:

#include <Wire.h>

const int X1 = PF0;
const int Y1 = PF1;
const int X2 = PF2;
const int Y2 = PF3;
//const int Bu1 = PA0;
//const int Bu2 = PA2;
//const int Bu3 = PA4;
//const int Bu4 = PA6;
const uint8_t SAD = 0x08;


int Y1SValue = 0;
int X1SValue = 0;
int Y2SValue = 0;
int X2SValue = 0;
//int Bu1SValue = HIGH;
//int Bu2SValue = 0;
//int Bu3SValue = 0;
//int Bu4SValue = 0;
//int BByte = 0;
byte dataArray[3] = {
  0, 0, 0
};

void setup()
{
  Wire.begin();                // join i2c bus with address #4
  //Wire.onRequest(requestEvent); // register event
  //pinMode(Bu1, INPUT_PULLUP);
  //pinMode(Bu2, INPUT_PULLUP);
  //pinMode(Bu3, INPUT_PULLUP);
  //pinMode(Bu4, INPUT_PULLUP);
}

void loop()
{
getdata();
transmit();
delay(30);
}

void getdata()
{
  Y1SValue = analogRead(Y1);
  X1SValue = analogRead(X1);
  Y2SValue = analogRead(Y2);
  X2SValue = analogRead(X2);
//  Bu1SValue = digitalRead(Bu1);
 // Bu2SValue = digitalRead(Bu2);
 // Bu3SValue = digitalRead(Bu3);
 // Bu4SValue = digitalRead(Bu4);
 // BByte = 0;
 // if (Bu1SValue = LOW){
 //   BByte = 1;
 // }
//  if (Bu2SValue = LOW){
 //   BByte = BByte+200;
  //}
 // if (Bu3SValue = LOW){
 //   BByte = BByte+30;
 // }
 //  if (Bu4SValue = LOW){
   // BByte = BByte+4;
   //}

     dataArray[0] = (map(X1SValue, 0, 1023, 0, 255));
     dataArray[1] = (map(Y1SValue, 0, 1023, 0, 255));
     dataArray[2] = (map(X2SValue, 0, 1023, 0, 255));
     //dataArray[3] = (map(Y2SValue, 0, 1023, 0, 255));
     //dataArray[4] = BByte;
}

void transmit()
{


// functionx   that executes whenever data is requested by master
// this function is registered as an event, see setup()
// void requestEvent()
  
  Wire.beginTransmission(SAD);
  Wire.write(dataArray, 3);
  Wire.endTransmission();
  

}

As I stated, the slave is an ATTINY, so I’m using the TinyWireS library. If I could, I would have had an “onReceive” mixed in, but the default library does not have that built in. Here’s that code:

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

#include "DigiJoystick.h"
#define SLAVE_ADDR 0x08

const uint8_t byreq = 0x08;
uint8_t result = 1;
uint8_t avby = 0;
int index = 0;
byte myBuf[3] = {
  0, 0, 0
};

void setup() {
  TinyWireS.begin(SLAVE_ADDR);        // join i2c bus (address optional for master)
  int index = 0;
  pinMode(1, OUTPUT);
  //TinyWireM.beginTransmission(MEGA_ADDR);
  //TinyWireM.write(0x00);
 // result = TinyWireM.endTransmission();
}

void loop() {
  avby = TinyWireS.available();
  int index = 0;
  if (avby > 0){
  requestData();
  }
  set_joy();
  digitalWrite(1, LOW);
  DigiJoystick.delay(10);
}

void requestData(){
  //TinyWireM.requestFrom(MEGA_ADDR, byreq);    // request 8 bytes from slave device SAD

    //int index = 0;
   //uint8_t avby = 0;
   //avby = TinyWireS.available();
   while (index <= 2) { // slave may send less than requested
       myBuf[index] = TinyWireS.receive(); // receive a byte as an integer
       index++;
          
     }
     digitalWrite(1, HIGH);
 }

 void set_joy(){
  DigiJoystick.setX((byte) myBuf[0]);
  DigiJoystick.setY((byte) myBuf[1]);
 // DigiJoystick.setXROT((byte) myBuf[2]);
 // DigiJoystick.setYROT((byte) myBuf[3]);
  //DigiJoystick.setZROT((byte) myBuf[2]);
  DigiJoystick.setSLIDER((byte) myBuf[2]);
  //int buttonByte = 0;
//     if myBuf[4] = 1000
 //  bitWrite(buttonByte, 0, myBuf[4]);
 //  bitWrite(buttonByte, 1, myBuf[5]);
 //  bitWrite(buttonByte, 2, myBuf[6]);
 //  bitWrite(buttonByte, 3, myBuf[7]);
//  DigiJoystick.setButtons((byte) buttonByte, (byte) 0);
  // it's best to use DigiJoystick.delay() because it knows how to talk to
  // the connected computer - otherwise the USB link can crash with the 
  // regular arduino delay() function
}

Does anyone have any ideas? I’ve checked how the master works in Serial, and it seems to get the data into a byte array without any problems. Any ideas?

Thanks everyone!

I see several problems. First, it seems you're driving the Tiny with 3V3 but you don't use a level converter for the I2C lines. The pull-ups to 3V3 aren't enough because the Mega2560 has onboard pull-ups and the Wire library activates the internal pullups additionally.
Second, the TinyWireS library. You didn't post a link to the version you're using and you didn't post a link to the Tiny core you're using in the IDE. Take a look at this project, we had several problems there with the TinyWireS library which got fixed with two patches: GitHub - boxtec/tinyLCD_I2C: Firmware for LCD I2C backpack based on ATtiny84.

how can I change a I2C libray that used wire.h to use the tinywire.h???

No code, no links -> no answer. The OP did not use a 'wire.h' file nor a 'tinywire.h' file and you don't provide a source for it. In the project I linked you cannot find a tinywire.h file too, so why do you think that we know what you are referring to?