[Solved] Interfacing with i2cget (problem reading a register)

Hello,

I’m trying to develop an I2C slave PID to control a PWM that will have register read and write functionality, to set P, I, D values and target temperature, and read current temperature, read current PWM duty, but I’m currently stuck on the I2C communication.

I’m using a 3.3V Pro Mini board, wired to a Raspberry Pi. I2C communication works fine.

Using i2cset is working as expected, as well as using i2cget WITHOUT data address. Problem is with i2cget with data address:

*** On the Pi:
root@pi:~# i2cset -y 1 0x4d 0x04 0x01

*** On the Arduino:
Incoming 2
Write reg
REG 0x4
VAL 0x1
*** On the Pi:
root@pi:~# i2cget -y 1 0x4d 0x7f
0x9b
root@pi:~# i2cget -y 1 0x4d
0xff

*** On the Arduino:
Incoming 1
Read reg
REG 0x7F
Read default
REG 0x7F

The code:

#include <Wire.h>
extern "C" {
  #include <utility/twi.h>
}

void setup() {
 Wire.begin(77);                // address 0x4d
 Wire.onRequest(requestEvent);
 Wire.onReceive(receiveEvent);
 Serial.begin(9600);
 Serial.println("ready");
}

void loop() {
 delay(100);
}


int reg;

void requestEvent() {
  Serial.println("Read reg");
  Serial.print("REG 0x"); Serial.print(reg,HEX); Serial.println();
  Wire.write(reg+128);
}

void receiveEvent(int rcv_sz) {
  int val;
  uint8_t reply[1]={0};
  uint8_t reply_sz=1;
  
  Serial.print("\nIncoming "); Serial.println(rcv_sz);
  
  switch(rcv_sz) {
    case 1: // get reg value
      Serial.println("Read reg");
      
      reg = Wire.read();
      
      Serial.print("REG 0x"); Serial.print(reg,HEX); Serial.println();

      reply[0]={127};
      twi_transmit(reply,reply_sz);
      twi_reply(1);
      
      if(Wire.available())
        Serial.println("data available");
      //switch(addr) {
      //  case '
      //}
    break;
    case 2: // set reg value
      Serial.println("Write reg");
      
      reg = Wire.read();
      val = Wire.read();
      
      Serial.print("REG 0x"); Serial.print(reg,HEX); Serial.println();
      Serial.print("VAL 0x"); Serial.print(val,HEX); Serial.println();
      // execute write code here
    break;  
    default: // flush garbage
      for (int a = 0; a < rcv_sz; a++)
        Wire.read();
     break;
  }
}

I think the value 0x9b is a sort of garbage sent because I did not set the reply value, but I’m unable to find where to set this value. Also I don’t get why i2cget trigger a receiveEvent only (i2cget code is actually requesting data after sending).

If someone has a solution, hint or even a clue on where to check…

 Wire.onRequest(requestEvent);
 Wire.onReceive(receiveEvent);

Pssst. These register callbacks for when a particular interrupt happens. Interrupts are disabled when the requestEvent() and receiveEvent() functions are running.

void requestEvent() {
  Serial.println("Read reg");
  Serial.print("REG 0x"); Serial.print(reg,HEX); Serial.println();
  Wire.write(reg+128);
}

It is a BAD idea to do things like Serial.print() in ISRs.

Thank you very much PaulS.

Removing all the Serial stuff solved it :)