Read analog Inputs via I2C Connection

Hello everybody,

i am trying to read all 16 analog inputs of an Arduino Mega (Slave) with a Raspberry Pi model 3B (Master) via an I2C Connection.

The connection itself works however i am having problems reading more than 4 inputs from the Arduino.

Here is the Code for the Raspberry:

import smbus
import time

bus = smbus.SMBus(1)

SLAVE_ADDRESS = 0x08

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

while True:
    var = input("Press any key for reading: ")
    requestreading()

And this is the code for the Arduino:

int SLAVE_ADDRESS = 0x08;
int analogPin1 = A0;
int analogPin2 = A1;
int analogPin3 = A2;
int analogPin4 = A3;    // ab 5 Werten Time Out oder I/O Error Raspberry
//int analogPin5 = A4;
//int analogPin6 = A5;
//int analogPin7 = A6;
//int analogPin8 = A7;
//int analogPin9 = A8;
//int analogPin10 = A9;
//int analogPin11 = A10;
//int analogPin12 = A11;
//int analogPin13 = A12;
//int analogPin14 = A13;
//int analogPin15 = A14;
//int analogPin16 = A15;


void setup(){
  Wire.begin(SLAVE_ADDRESS);
  
    Serial.begin(115200);



  Wire.onRequest(sendAnalogReading);
}

void loop(){
  
}

void sendAnalogReading(){
  int reading1 = analogRead(analogPin1);
  int reading2 = analogRead(analogPin2);
  int reading3 = analogRead(analogPin3);
  int reading4 = analogRead(analogPin4);
//  int reading5 = analogRead(analogPin5);
//  int reading6 = analogRead(analogPin6);
//  int reading7 = analogRead(analogPin7);
//  int reading8 = analogRead(analogPin8);
//  int reading9 = analogRead(analogPin9);
//  int reading10 = analogRead(analogPin10);
//  int reading11 = analogRead(analogPin11);
//  int reading12 = analogRead(analogPin12);
//  int reading13 = analogRead(analogPin13);
//  int reading14 = analogRead(analogPin14);
//  int reading15 = analogRead(analogPin15);
//  int reading16 = analogRead(analogPin16);

  Wire.write(reading1);
  Wire.write(reading2);
  Wire.write(reading3);
  Wire.write(reading4);
//  Wire.write(reading5);
//  Wire.write(reading6);
//  Wire.write(reading7);
//  Wire.write(reading8);
//  Wire.write(reading9);
//  Wire.write(reading10);
//  Wire.write(reading11);
//  Wire.write(reading12);
//  Wire.write(reading13);
//  Wire.write(reading14);
//  Wire.write(reading15);
//  Wire.write(reading16);

}

The Problem is that as soon as i start to read from more than the first 4 analog Pins i get an error that the connection timed out or that there is an I/O Error.

The int for Arduino is 2 byte so in theory i should be able to read all 16 analog inputs as read_i2c_block_data command allows to read 32 byte at once.

Does anybody have an idea why i can't read more than 4 inputs? Is this maybe a timing issue with the i2c connection?

Your ISR should send the last readings that happened before the ISR was called. It should NOT be reading the analog pins. The loop() function should do that.

The ISR should contain only ONE call to write() to write all 16 values (32 bytes) from an array.

You can't read them all simultaneously. You need to multiplex and read them one at a time. For example:

ISR(ADC_vect) {
	if (ADMUX == 0x00) {
		result1 = ADCL | (ADCH << 8);
		ADMUX = 0x01;
	}
	else if (ADMUX == 0x01) {
		result2 = ADCL | (ADCH << 8);
		ADMUX = 0x00;
	}
	
	/* Start the next conversion */
	ADCSRA |= (1 << ADSC);
}

I agree with PaulS.

Could you try this and see how far you get?

volatile int16_t data[16];

void loop()
{
  for( int i = 0; i<16; i++)
  {
    data[i] = analogRead( A0 + i);
  }
}

void sendAnalogReading()
{
  Wire.write( (uint8_t *) data, sizeof( data));
}

Or perhaps this:

volatile int16_t data[16];

void loop()
{
  int16_t temporary[16];
  for( int i=0; i<16; i++)
  {
    temporary[i] = analogRead( A0 + i);
  }
  noInterrupts();
  memcpy( (void *) data, temporary, sizeof( data));
  interrupts();
}

void sendAnalogReading()
{
  Wire.write( (uint8_t *) data, sizeof( data));
}