I2C connection with Pi to take commands and report back values

I am doing my first I2C communication and am stuck in a bit of quagmire. I finally got through the formation of the data, where I store all data to be sent from Arduino (slave) to Pi (master). I store all data in the same datatype and create an array to send to the pi.

Now, I would like to do two things. One is that the Pi sends request to the Arduino, telling it to take a set of readings and send back the values. I can do this now with Wire.onRequest(requestEvent);, though I don't know if in real world conditions it will work like that because the readings may take too much time and time out.

The next thing I want to do is have the Pi send the arduino a command that tells it to do a certain command from a list of commands. For instance, if the pi sends 'a', then do Action A, if 'b', do Action B. From working with smbus on the Pi, I think I will have to send numbers.

I've coded this in the onRequest(requestEvent) and onReceive(receiveEvent), but even when call bus.write_byte(addr,97) on the Pi, it doesn't execute onReceive and instead executes requestEvent.

void receiveData(int byteCount) {
  while(Wire.available()) {
    byte input = Wire.read();
    Serial.println(input);
    if (input == 97) {
      //requestEvent();
      int fake2[] = {2,1,29};
      Wire.write((byte *)&fake2,6);
    }
    
  }
}
void requestEvent() {
  unsigned long value = millis();  
  int fake[] = {2,2122,3232};
  Wire.write((byte *)&fake,6);
}

, though I don't know if in real world conditions it will work like that because the readings may take too much time and time out.

loop() should be doing the reading of the sensors. The I2C callback should instantaneously report the latest readings.

but even when call

Taken completely out of context, the snippet of code is useless.

Post ALL of your code for both sides.

Here is Arduino:

#include <Wire.h>

byte apin1 = A1;
byte apin2 = A2;
byte dpin1 = 5;
byte dpin2 = 6;

byte b = 0;
void setup() {
  Serial.begin(9600);
  pinMode(dpin1, OUTPUT);
  pinMode(dpin2, INPUT_PULLUP);
  Wire.begin(0x09);                // join i2c bus with address #9
  Wire.onRequest(requestEvent); // register event
  Wire.onReceive(receiveData);
}

void loop() {
  delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  unsigned long value = millis();  
  int aread = 133;//analogRead(apin1);
  byte ahigh = 12;//highByte(aread);
  byte alow = 3;//lowByte(aread);
  int fake[] = {2,2122,3232};
  Wire.write((byte *)&fake,6);
  Serial.println("Request fired.");
}


void receiveData(int byteCount) { // took out byteCount
  byte x;
  String rest= "";
  for (int i = 0; i < byteCount; i++) {
    if (i == 0) {
      x = Wire.read();
    }
    else {
      char c = Wire.read();
      rest = rest + c;
    }
  }
  if (x == 0x05) {
    Serial.println("0x05 confirmed");
    int fake2[] = {2,1,29};
    Wire.write((byte *)&fake2,6);
  }
}

And here is the Pi:

import smbus
import struct
import time

bus = smbus.SMBus(1)
bus.write_byte(0x09,0x05)
time.sleep(1)
ardtime = bus.read_i2c_block_data(0x09,0)
print(ardtime)

What happens is that the Arduino executes the Request and Receive operations, but I only get the data from the Request, If I change the 0x05 to something else, just the Request.

I am trying to be able to get it to just execute the Receive and not the Request.

  Serial.println("Request fired.");

In an interrupt service routine? No!

void receiveData(int byteCount) { // took out byteCount

Doesn’t look to me like you took the argument out. The Wire library defaults to 32 byte or smaller packets. Do you really need an int for that?

  for (int i = 0; i < byteCount; i++) {

Same question.

  String rest= "";

Pissing away resources uselessly is never a good idea.

    Serial.println("0x05 confirmed");

In an interrupt service routine? No!

ardtime = bus.read_i2c_block_data(0x09,0)

What is this supposed to be doing?

I changed the last line to

firsttime = bus.read_i2c_block_data(0x09,0x01,12)

I still don't know what that middle number does, but changing it doesn't affect the readout. I just want 12 bytes back and it does that.

Once purpose of the code is to get back the data from the Request action. I haven't figured out what I need to do to get the data back from the Receive call.

As for the Serial and other stuff, that was just troubleshooting. I should've taken it out before sharing the code.