12

I am testing i2c communication between Pi and Arduino.

The doc says:

write_i2c_block_data(addr,cmd,vals)  Block Write transaction.    int addr,char cmd,long[]    None

I have this test:

On Pi:

import smbus
bus = smbus.SMBus(0)
bus.write_i2c_block_data(address, 48, [49, 50, 51] )

On Arduino:

void receiveData(int byteCount){
    Serial.print("byte count=");
    Serial.println(byteCount);

    while(Wire.available()) {
        number = Wire.read();
        Serial.print((char)number);
     }
}

On the Arduino I see this output:

byte count=4
0123

My question is: what is the use of the cmd parameter? I don't see a distinction on the Arduino of which byte represents what.
I guess I can deal with it as a see fit. Maybe I want to use the first 2 bytes as a command.

This page has not much information on the method: http://wiki.erazor-zone.de/wiki:linux:python:smbus:doc

  • You may want to define what the cmd parameter is... I had to do a fair bit of looking to figure out what you meant. I didn't find an answer though... It may only be used by specific chips like a GPIO expander or something... – Butters Jul 17 '13 at 3:42
  • Ok, I added the link to the documentation (which is not much) – Gus Smith Jul 17 '13 at 4:54
  • 6
    I have no time to make a full answer right now (I hope someone will) but in short - this is how I²C works. Master can just send it some bytes of data (after sending proper address) and there is no specification on what those bytes actually are (their meaning is defined per device). It just so happens that the first byte is often a command (or register) number. Also you always have to send at least one byte so unlike vals, cmd is mandatory. – Krzysztof Adamski Jul 17 '13 at 8:58
  • 1
    @KrzysztofAdamski That sounds like a pretty complete answer to me. – Butters Jul 17 '13 at 13:37
9

I²C protocol is very simple. It does not really define data structures that are sent over the wire. The frame consist of a slave address (with direction bit indicating if master wants to read or write) and (in case of writing) some bytes of data. Since it doesn't make sense to initiate write with 0 bytes of data, first byte is mandatory.

This first byte is often used as a slave register address or command number but it doesn't have to. There may or may not be additional bytes after the first one. The higher level protocol defining what each byte means is device specific.

This may explain why there are two separate arguments - first one (cmd) is mandatory and second one (vals) is optional. While your example is in Python language, the API used here is actualy very close mapping of original C API where you can't easly create optional arguments.

| improve this answer | |
  • This is a little longer explanation of what I wrote in the comment under the question. – Krzysztof Adamski Jul 17 '13 at 17:01
  • I'm glad you did! These kinds of simple, yet "aha!" explanations are really helpful some times, like today :-) – uhoh Jan 19 '18 at 7:08
3

When you issue a block write/read from the Pi with:

bus.write_i2c_block_data(address, 48, [49, 50, 51] )

or

bus.read_i2c_block_data(address, 48, [49, 50, 51] )

Two things happen(can) on the Arduino depending on read or write.

The cmd byte is the first byte written to the I2C bus from the Pi, it is always sent as a "write" request. This means that if the Pi is issuing a

bus.read_i2c_block_data

or

bus.write_i2c_block_data

it first writes

cmd

to the I2C bus before it reads.

This is a useful feature because some I2C hardware requires initialization before a read can be made.

On the Arduino this means that:

First the,

Wire.onReceive(yourCallback)

function is called because cmd was written to the bus by the Pi. cmd will be the first byte available on the bus. If the Pi sent write request than the Arduino will stay in the Wire.onReceive callback until the function is complete. If the Pi sent a read request, the Arduino will complete the Wire.onReceive then call the Wire.onRequest callback.

You must ensure that the value placed in cmd does not cause unintended behavior in your system by appropriately handling its value. If for example, your Wire.onReceive call back turns off an LED when the Wire.read=0x30. Then even if you sent a read request, it would first turn OFF the LED by writing 0x30 then it would read the requested bytes from the bus.

| improve this answer | |
1

I am writing to an I2C LCD, the Newhaven NHD‐0216K3Z‐FL‐GBW‐V3. Its spec sheet can be googled. In its case, when the command byte is 0xfe it means that the following byte is a command - there are about 20 of them. Clear, backlight, blink cursor and so on. If cmd is not 0xfe it is just some character to display.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.