Wire.onReceive not working within class

Hello, recently I have dedicated myself to learning OOP, however, I have run into some difficulties. I am writing a class to handle receiving communications from another Arduino over I2C, this involves starting a connection with the other Arduino and assigning a function using "Wire.onReceive" This is where I run into issues.

Below is my simple sketch

#include <Wire.h>
class hardwire {
  private:
  byte _rx;

  public:
  void hardwireStart(){
    Wire.begin();
    Wire.onReceive(hardwireReceive);
  }

  static void hardwireReceive(int bytes){
    _rx = Wire.read();
  }

};

hardwire chip;

void setup() {
  chip.hardwireStart();
}

void loop() {

}

When compiled this returns the error

A:\code\code.ino: In static member function 'static void hardwire::hardwireReceive(int)':
StationMVC:13:5: error: invalid use of member 'hardwire::_rx' in static member function
     _rx = Wire.read();
     ^~~
A:\code\code.ino:4:8: note: declared here
   byte _rx;
        ^~~
exit status 1
invalid use of member 'hardwire::_rx' in static member function

From my initial research, this appears to be an issue with handlers being incompatible with classes. However, my understanding of this topic is far too thin to make sense of the issue.

For reference, here is what my original (working, without classes) looked like:

byte _rx;
#include <Wire.h>

void setup() {
  Wire.begin();
  Wire.onReceive(hardwireReceive);

}

void hardwireReceive(int bytes){
  _rx = Wire.read();
}

void loop() {

}

Is this fixable? Or should I just give up and create a separate function outside of the class for Wire.onReceive.

Hello,

It's probably because _rx is not static. Static methods cannot access non-static members

1 Like

You have to provide a function handle to the onRecive method but you tried to provide a method. This cannot work because the calling interrupt doesn't know about the used instance of your class.

Make a routine outside your class, that calls chip.hardwireReceive() to provide the instance to the method and this will work.

No I think it should work after replacing
byte _rx;
to
inline static byte _rx = 0;

Here is an example : https://ideone.com/2aKiJr

1 Like

Great, it seems to compile! I'll test it later today.

One issue I have is that I don't understand the problem, I understand some of your terminology such as "static" in the term of variables. However most of this I don't understand.

Why does _rx, have to be static, how can a method be "static"?

This sounds like you are saying one of my methods is static, yet I never declared it as such? Noticed that it was declared in my code as a previous fix, my bad.

What is the use of "inline"?

Any good source to understand this would be appreciated (or just any source to learn OOP from the ground up, instead of in bits and pieces).

Thanks again.

Read this to understand "static" inside classes : Static Members of a C++ Class

Especially the part "Static member functions" (what I called "static method", same thing)

Note, in the example they used in the class definition static int objectCount; then later it is initialized with int Box::objectCount = 0;. This is basically the same thing as doing inline static int objectCount = 0; in the class definition.

But how will your class be used ? Do you plan to have more than one hardwire object ?

I'll take a look at it! Thanks :grinning:

While simple, right now, this is only an isolated part of my class, the full class features ways for main code to interact with the other device, simplifying everything that made up "spaghetti" in my old code.

Not in this case, only one.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.