I am using Python smbus write_word_data method to send int values from a Raspberry Pi to an Arduino using I²C.

This seems to be the correct method.

When I send values from 0-255, I see the following in my Arduino serial monitor



Sending 256 I see:


For 257 I see:


Etc, etc...

My question is, how would I modify the following Arduino code to properly 'reconstitute' the int values, and then send them back to the RPi?

#include <Wire.h>

#define SLAVE_ADDRESS 0x04
int number = 0;
int state = 0;
bool newData = false;

void setup() {
  pinMode(13, OUTPUT);
  // initialize i2c as slave
  // define callbacks for i2c communication

void loop() {

// callback for received data
void receiveData(int byteCount) {
  while(Wire.available()) {
    newData = true;
    if(Wire.available() == 2) {
      receivedValue = Wire.read() | Wire.read() << 8;

// callback for sending data
void sendData() {
  • 2
    Aren't you really transferring these over i2c, not (asynchronous) serial as implied in the title, and using the serial more as a debug monitor to tell what is going on? Commented Jul 22, 2014 at 17:45

3 Answers 3

void receiveData(int byteCount){

  // Looks like your number is sent in a 3 byte packet
  if (bytecount == 3)

    // Discard first number as it is seemingly alway zero

    // Read low byte into rxnum
    int rxnum = Wire.read();

    // Read high byte into rxnum
    rxnum += Wire.read() << 8;

    // Send back



void sendInt(int num){

  // Uncomment below if you want so send back in same format
  // Wire.write(0);

  // Send low byte

  // Send high byte
  num >>= 8;
  • Just to clarify. Wire.read() and Wire.write only work of single bytes. To send a 2 byte int, you need to split the int into 2 bytes, send them individually, and then join them again at the receiving end.
    – Gerben
    Commented Jul 22, 2014 at 20:45
  • thanks!. I've edited my original code and it works, but how do I separate out my x,y coordinates in my main loop? Serial.println(receivedValue);
    – Bachalo
    Commented Jul 23, 2014 at 15:00
  • This likely won't work as op expects. Each write(byte) transmits in separate transactions. If the master calls this with requestFrom(), it'll only receive the first byte, and never receive the second. To send both bytes, you need to pass a byte array to write().
    – Cerin
    Commented Sep 20, 2016 at 20:19

Ir seems to me that there is something wrong with the Python Raspberry Pi code. What you show is 3 bytes of data, not 2. That's wrong.

If you're writing a 2 byte word, I would expect to see 2 bytes, not 3. You might want to post a question on the Raspberry Pi forum to get help resolving THAT problem first.

If you're stuck with the sending code you have, then here's what you would do.

Looking at your data, the first byte is always zero. You want to discard it.

The second byte is your low order byte, and your third byte of data is the high order byte. You need to do some juggling to get the data into the correct byte order, like this:

void readWordWithPadding()
  if (Wire.available()<3)
    newData = false;
    newData = true;

  Wire.read(); //Throw away the filler byte
  int lowByte = Wire.read();
  int hiByte = Wire.read();

  //Shift the high byte by 8 bits and add in the low byte
  receivedValue = (hiByte << 8) + lowByte ;
  • Thanks. The remaining problem is separating out my x,y values. On the sending side I call writeNumber(x) then writeNumber(y). So In my arduino code receivedValue alternates between x&y. But having a problem separating the 2.
    – Bachalo
    Commented Jul 23, 2014 at 15:38
  • That is a design problem. You need to coordinate what is sent from the Pi with what you look for on the Arduino side. If you're always sending an X/Y pair, then you should write your Arduino code to look for an X/Y pair. Always read both numbers. You might need to adjust your code logic to make sure 4 bytes (or 6 bytes if you haven't been able to get rid of those spurious zero bytes) are available before starting to read.
    – Duncan C
    Commented Jul 23, 2014 at 18:43

Unless (and until) your application needs high enough data rates that you need to make the most efficient use possible of your data channel (or you're talking to an inflexible hardware device that dictates the data protocol), you'll save yourself a lot of headaches by sending human-readable strings, something like:

x= 12345, y=   -32
x=   432, y=-33221

You can reconstitute them at the other end with with atol(), log them to a file, be able to understand them later, and see instantly whether the sender sent what you expected it to. Don't optimize until you have to; you may not have to.

Your Answer

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

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