2

I am trying to read some values from a Arduino microcontroller by sending a read request from my PC, but instead of triggering the request callback it is triggering the receive, which does not make sense at all? I am running I2C hence SMBus seems to be significantly slower.

Arduino code:

void dataReceive() {
    Serial.println("Receive");
}


void dataRequest() {
    Serial.println("Request");
    Wire.write(1);
}

void setup()
{
    Wire.begin(4);
    Wire.onReceive(dataReceive);
    Wire.onRequest(dataRequest);
}

PC code:

import smbus
bus = smbus.SMBus(1)

data = bus.read_i2c_block_data(0x04, 0x09, 1)
print data

I get following error aswell:

Traceback (most recent call last):
  File "./i2ctest.py", line 16, in <module>
    data = bus.read_i2c_block_data(0x04, 0x09, 1)
IOError: [Errno 11] Resource temporarily unavailable

Although i am able to see in the Arduino serial monitor that the dataReceive callback is triggered.

1 Answer 1

1

Arduino has no repetitve start signal in Wire.h library. Your solution is something like this:

On Arduino side:

void dataReceive() {
    x = 0;
    for (int i = 0; i < byteCount; i++) {
        if (i==0) {
            x = Wire.read();
            cmd = ""
        } else {
            char c = Wire.read();
            cmd = cmd + c;
        }
    }
    if (x == 0x09) {
        // Do something arduinoish here with cmd if you need no answer
        // or result from Arduino
        x = 0;
        cmd = ""
    }
}

This will store the first character of the received ones as a "command" then the rest will be the arguments part. In your case command is 0x09, argument is 1.

On PC side the python command is this:

bus.write_i2c_block_data(0x05,0x09,buff)

Where buff is "1".

You might need the datarequest event:

void dataRequest() {
    x = 0;
    Wire.write(0xFF);
}

This will send back a simple FF.

If you need answer from the arduino, then process the cmd parameter here. In this case on python side you will need more:

bus.write_i2c_block_data(0x05,0x09,buff)
tl = bus.read_byte(0x05)

This sends "1" into command "0x09" to device "0x05". You will then fetch the answer with a read command simply from device "0x05".

Sign up to request clarification or add additional context in comments.

7 Comments

In order to avoid doing "writes" from the master and reduce overhead, i was considering using the write to set a mode and thereafter simply check the mode in dataRequest and send the data back to the master according to the last set mode. So i set one mode with write and simply read afterwards. Seems a bit unorthodox, but write/read all the time seems to polute the bus with excessive data.
Yes, if you need no data to send, then a simple bus.write_byte() command is enough to set the "mode" on Arduino side.
I still have an issue here. I need to put a small delay between the write and read before i receive anything useful. Should the timing not be set by the clock frequency of the I2C?
Normally the client must answer immediately for a request, at least something like "not ready" and the master has to implement the timing function. Eg. the client is a thermometer and measured data is available in every 2 secs, it is the master who required to wait to fetch new data. In other case the client would block the bus! If your arduino side requires complex operands the best way is to put everything into the main loop, protect that part from any interrupt, store the result in a global variable and when the master triggers for any result you need to send back the global variable only.
Basically the only thing that onRequest does is sending data which is fetched from a IMU. The IMU data is read in the main-loop. I basically only experience this issue when i do a write and read after each other. If i read continuously theres no issue at all.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.