Pull up resistors Arduino mega I2C communication

Hi everybody,

if i am reading analog values from my mega A0-A3 and then want to transmit the values via I2C to a raspi, do i need separate pullup resistors?

My current Arduino code looks like this:

#include <Wire.h>

int SLAVE_ADDRESS = 0x08;
int analogPin1 = A0;
int analogPin2 = A1;
int analogPin3 = A2;
int analogPin4 = A3;


void setup(){
  Wire.begin(SLAVE_ADDRESS);
  Wire.onRequest(sendAnalogReading);
}

void loop(){
  
  
}

void sendAnalogReading(){
 
  uint16_t reading1 = analogRead(analogPin1);
  uint16_t reading2 = analogRead(analogPin2);
  uint16_t reading3 = analogRead(analogPin3);
  uint16_t reading4 = analogRead(analogPin4);


Wire.write((char *) &reading1, 2);
Wire.write((char *) &reading2, 2);
Wire.write((char *) &reading3, 2);
Wire.write((char *) &reading4, 2);

}

The python script on the raspberry looks like this:

 import smbus
import time


bus = smbus.SMBus(1)

SLAVE_ADDRESS = 0x08

def requestreading():
    block = bus.read_i2c_block_data((SLAVE_ADDRESS), 0, 8)

    print(block)


while True:
    #var = input("Press any key for reading: ")
    requestreading()
    time.sleep(0.1)

    #n = input("Please enter 's':")
    #if n.strip() == 's':
        #break

The code runs for a few seconds before it returns the message on the raspi:

 Traceback (most recent call last):
      requestreading()
block = bus.read_i2c_block_data((SLAVE_ADDRESS), 0, 8)
OSError: [Errno 121] Remote I/O error

i am wondering if this might be a problem with the pullup resistors on the Arduino Mega.

MEGA has built-in pull up resistors on the I2C Bus.
megaPullupI2Cx.png

megaPullupI2Cx.png

As the Mega as internal onboard pull-ups to 5V (as GolamMostafa already explained) the corresponding pins on the Raspberry Pi are treated with 5V. The protection diodes will probably catch the over-voltage for some time but it's quite probable that the I2C function is limited as the circuit is not made to sink 5V. You have to use level converter if you connect a Raspberry Pi to a Mega or desolder the Mega's pull-up resistors and deactivate the activation of the internal pull-ups in the Wire library just to insert pull-ups to 3V3 on either side.

@pylon If i run the programs in their current form without a level shifter the code runs for some time before it crashes, giving me the error on the Raspi: "OSError: [Errno 121] Remote I/O error"

Depending on how long i set the time.sleep() in the loop of on my Raspi script the code runs longer or shorter until the error message appears and the program cuts out.

Do you think this could have something to do with the non present level shifter?

Do you think this could have something to do with the non present level shifter?

I wouldn't waive it.

I see a problem in your code too although I doubt that this is causing the error you get.
You read the analog pins in the interrupt context of the onRequest routine (sendAnalogReading). Analog reads need a lot of time so you should do the reads in the interrupt context. Read the analog values in the loop, save the values into variables declared as volatile (so they are accessible in the interrupt context) and just send them in the onRequest handler.

Insert a Serial.print() statement into your loop to check if the Arduino is hanging or if the Raspi has some problem.

@pylon I have now integrated an Texas Instrument TXS0108E and that has improved the stability of my program by a lot. However it still crashes eventually with the same error message as before. I am guessing that the raspi is getting a value that is between 1.2V and 2.4V and therefore cannot place it as high or low and goes into error mode. Do you think this might be possible?

could you maybe give me a short version of what your code adjustment would look like?

This is just pseudo code but it should show you what I mean:

volatile uint16_t val = 0;

void setup() {
  Serial.begin(57600);
  Wire.begin(44);
  Wire.onRequest(myOnRequest);
}

void loop() {
  val = analogRead(A0);
  Serial.println("Still alive");
}

void myOnRequest() {
  Wire.write(&val, 2);
}