Raspberry Pi Stack Exchange is a question and answer site for users and developers of hardware and software for Raspberry Pi. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have connected Raspberry pi 2 model B with arduino uno via Bi-Directional Level shifter.

Raspberry pi    GND    ----------   GND     Arduino
                3.3v   ----------   5v
                SCL    ----------   A5
                SDA    ----------   A4

Hope my I2C connection is correct ?

and my Arduino is connected to 8-Channel Relay Board.

Now I have written code in which I can control the Relay board by Raspberry pi. For ex if i Press '1' the Relay 1 goes high.

Now I want to send data back from arduino to raspberry pi in order to cross check if Relay 1 is high or not, if Relay 1 is high then it should send some data back to Raspberry pi or else not.

My Rpi code is

import smbus
import time
# for RPI version 1, use "bus = smbus.SMBus(0)"
bus = smbus.SMBus(1)

# This is the address we setup in the Arduino Program
address = 0x04

def writeNumber(value):
    bus.write_byte(address, value)
    # bus.write_byte_data(address, 0, value)
    return -1

def readNumber():
    number = bus.read_byte(address)
    # number = bus.read_byte_data(address, 1)
    return number

while True:
    var = input("")
    if not var:
        continue

    writeNumber(var)
    number = readNumber()

My Arduino code:

#include <Wire.h>

#define SLAVE_ADDRESS 0x04
#define RELAY1 9

int number = 0;
int state = 0;

void setup() {
    pinMode(RELAY1, OUTPUT);

    Serial.begin(9600); // start serial for output
    // initialize i2c as slave
    Wire.begin(SLAVE_ADDRESS);

    // define callbacks for i2c communication
    Wire.onReceive(receiveData);
    Wire.onRequest(sendData);

    Serial.println("Ready!");
}

void loop() {
    delay(100);
}

// callback for received data
void receiveData(int byteCount){

    while(Wire.available()) {
       number = Wire.read();
       Serial.print("data received: ");
        Serial.println(number);

        if (number == 1){

            if (state == 0){
                digitalWrite(RELAY1, HIGH); // set the LED on
                state = 1;
            }
            else{
                digitalWrite(RELAY1, LOW); // set the LED off
                state = 0;
            }
        }
    }
}

// callback for sending data
void sendData(){
    Wire.write(number);
}

Now if I type 1 and due to some loose connection Relay 1 doesn't goes high, So in this case I want the arduino to take data from relay board and send it to Raspberry pi every time.

It will be great if someone can explain also that how it works.

Hope I was able to explain the problem. I have done lots of research but was not able to find some answer.

I am a beginner in python so please help me.

Thanks in advance.

share|improve this question

First off, the wiring is wrong. Raspberry Pi will burn if you put 5V at its 3.3V power pins. However due to how the I2C protocol works you don't need a logic level translator for the I2C lines.

Also, it would be a better idea to use a GPIO pin on each end to function as a interrupt pin so your Pi don't have to poll on the I2C bus. You can do something like this:

schematic

simulate this circuit – Schematic created using CircuitLab

The Raspberry Pi have built-in pull-ups to 3.3V rail so you don't need your own pull-ups. The 4.7kΩ resistor on the IRQ# line will prevent the current flowing from the 5V Arduino from burning out the 3.3V circuit, saving a translation mechanism.

As of the code, it is mostly right. I cannot spot any issues yet.

share|improve this answer
    
I think we need to use Logic level conveter when Arduino sends data to Raspberry pi. I took the connection diagram from blog.oscarliang.net/raspberry-pi-arduino-connected-i2c – shivam Mar 9 at 5:15
    
Hey I also know that this code works fine, I need addition in this code that is how to send data back to raspberry pi from arduino. – shivam Mar 9 at 5:17
    
@shivam You don't really need level conversion as the I2C standard defined a compatible 5V and 3.3V logic levels (not your standard TTL or CMOS levels) and as long as the pull-up don't shoot over either end's supply rail there is no risk of burning anything. I have a similar project that an ATmega328P at 5V and a Pi talk over I2C this way. You can use additional level clamping diodes if you want to. – Maxthon Chan Mar 11 at 6:31
    
Thanks @Maxthon Chan but When i send data from Arduino to raspberry pi i.e. sending data from 5v to 3.3v, it may burn up the raspberry pi if the voltage is above 3.3v so I used I2C level converter. Well do you know about how to send the Digital Read pins data from arduino to raspberry pi?. I mean how to use the DigitalRead() command. I am pretty new to Python laguage. – shivam Mar 11 at 6:36
1  
@shivam The entire I2C bus operate at 3.3V even though the 328P is powered by a 5V rail. – Maxthon Chan Mar 11 at 6:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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