Using I2C with Raspberry Pi

I am attempting to communicate with the arduino through I2C. The arduino is set up a slave and a raspberry pi as master. I want to write a value to the arduino, depending on this value the arduino writes a string back. I will always write a value before requesting data. I can't seem to get this to work. My code is as below:

#include <Wire.h>

int measurement = 0;
bool readComplete = false;


void setup() {
  Serial.begin(9600);
  Wire.begin(0x9);
  Wire.onReceive(receiveFunction);
  Wire.onRequest(requestFunction);
}

void receiveFunction(int howmany){
  if(readComplete == false){
    measurement = Wire.read();
    readComplete = true;
    Serial.print("read complete: ");
    Serial.print(readComplete);
  }
}

void requestFunction(){
  if(readComplete){
    Serial.print("\nRequested: ");
    Serial.print(measurement);
    Serial.print("\n");
    switch (measurement) {
      case 1:
        Serial.print("Sensor 1");
        Wire.write("1.11");
        break;
      case 2: 
        Serial.print("Sensor 2");
        Wire.write("2.22");
        break;
      default:
        Serial.print("Default\n");
        Wire.write("3.33");
        break;
        }
    readComplete = false;
    Serial.print("Read Complete: ");
    Serial.print(readComplete);
    Serial.print("\n");
   }
}

void loop() {}

For some reason whenever I request data from the I2C, that is I attempt to read the value from the value, the arduino registers a write before sending the data. For example master writes 2 to the arduino -> master reads data -> This read rereads measurement to 0 (not sure why) -> Switch defaults and writes 3.33. I can repeat this with different numbers without reseting the arduino but I always get the default.

In an attempt to get around this I introduced the global variable as above. This works as a flag to ensure measurement is only set AFTER a master read. Then I request data in the order master write -> master read -> master write -> master read etc. The boolean is correctly set and reset as evident by monitoring the serial, however, I can't request any data. The arduino acknowledges its address but simply writes [1, 255, 255, 255], I assume because it is no longer pulling the I2C low. I have to reset the arduino, after which it works once, fulfilling one master write -> master read cycle before the arduino needs to be reset again.

Any help anyone could give would be greatly appreciated!

The Arduino I2C slave code here may help: Gammon Forum : Electronics : Microprocessors : I2C - Two-Wire Peripheral Interface - for Arduino
In the I2C call back routines, you should not use Serial.print(). If you need status information, set a global flag (defined as volatile) in the call back routine and read it in the loop() to control any printing.

When the Master requests data, how does the Master know that the Slave sends "3.3" or "3.33" or "3.333" ? :o :confused: :cold_sweat: :cry:

Can you connect the Arduino with a USB cable to the Rapsberry Pi ? Then you can use Serial/UART communication. There is a library for it, with a Python script for the Raspberry Pi. As a bonus, it is possible to upload a sketch to the Arduino (even with the command line if you run the Raspberry Pi headless).

I wrote a page to scare new user who think that the I2C can do those things without problems: How to make a reliable I2C bus · Koepel/How-to-use-the-Arduino-Wire-library Wiki · GitHub.

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