├── RaspberryPi └── i2c.py ├── Arduino └── firmware │ └── firmware.ino └── README.md /RaspberryPi/i2c.py: -------------------------------------------------------------------------------- 1 | import RPi.GPIO as gpio 2 | import smbus 3 | import time 4 | import sys 5 | 6 | bus = smbus.SMBus(1) 7 | address = 0x04 8 | 9 | def main(): 10 | gpio.setmode(gpio.BCM) 11 | gpio.setup(17, gpio.OUT) 12 | status = False 13 | while 1: 14 | gpio.output(17, status) 15 | status = not status 16 | bus.write_byte(address, 1 if status else 0) 17 | print "Arduino answer to RPI:", bus.read_byte(address) 18 | time.sleep(1) 19 | 20 | if __name__ == '__main__': 21 | try: 22 | main() 23 | except KeyboardInterrupt: 24 | print 'Interrupted' 25 | gpio.cleanup() 26 | sys.exit(0) 27 | -------------------------------------------------------------------------------- /Arduino/firmware/firmware.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define SLAVE_ADDRESS 0x04 4 | #define LED 13 5 | 6 | int number = 0; 7 | 8 | void setup() { 9 | pinMode(LED, OUTPUT); 10 | Serial.begin(9600); 11 | Wire.begin(SLAVE_ADDRESS); 12 | Wire.onReceive(receiveData); 13 | Wire.onRequest(sendData); 14 | 15 | Serial.println("Ready!"); 16 | } 17 | 18 | void loop() { 19 | delay(100); 20 | } 21 | 22 | void receiveData(int byteCount) { 23 | Serial.print("receiveData"); 24 | while (Wire.available()) { 25 | number = Wire.read(); 26 | Serial.print("data received: "); 27 | Serial.println(number); 28 | 29 | if (number == 1) { 30 | Serial.println(" LED ON"); 31 | digitalWrite(LED, HIGH); 32 | } else { 33 | Serial.println(" LED OFF"); 34 | digitalWrite(LED, LOW); 35 | } 36 | } 37 | } 38 | 39 | void sendData() { 40 | Wire.write(number); 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Arduino and Raspberry Pi working together (with i2c) 2 | ====== 3 | 4 | The most easy way to connect our Arduino board to our Raspberry Py is using the USB cable, but sometimes this communication is a nightmare, especially because there isn't any clock signal to synchronize our devices and we must rely on bitrate. There're different ways to connect our Arduino and our Raspberry Py such as I2C, SPI and serial over GPIO. Today we're going to speak about I2C, especially because it's pretty straightforward if we take care with a couple of things. Let's start. 5 | 6 | I2C uses two lines SDA(data) and SCL(clock), in addition to GND (ground). SDA is bidirectional so we need to ensure, in one way or another, who is sending data (master or slave). With I2C only master can start communications and also master controls the clock signal. Each device has a 7bit direction so we can connect 128 devices to the same bus. 7 | 8 | If we want to connect Arduino board and Raspberry py we must ensure that Raspberry pi is the master. That's because Arduino works with 5V and Raspberry py with 3.3V. That means that whe need to use resistors if we don't want destroy our Raspberry pi. But Raspberry pi has 1k8 ohms resistors to the 3.3 votl power rail, so we can connect both devices (if we connect other i2c devices to the bus they must have their pull-up resistors removed) 9 | 10 | Thats all we need to connect our Raspberry pi to our Arduino board. 11 | * RPi SDA to Arduino analog 4 12 | * RPi SCL to Arduino analog 5 13 | * RPi GND to Arduino GND 14 | 15 | Now we are going to build a simple prototype. Raspberry pi will blink one led (GPIO17) each second and also will send a message (via I2C) to Arduino to blink another led (controlled by Arduino). That's the Python part 16 | 17 | ```python 18 | import RPi.GPIO as gpio 19 | import smbus 20 | import time 21 | import sys 22 | 23 | bus = smbus.SMBus(1) 24 | address = 0x04 25 | 26 | def main(): 27 | gpio.setmode(gpio.BCM) 28 | gpio.setup(17, gpio.OUT) 29 | status = False 30 | while 1: 31 | gpio.output(17, status) 32 | status = not status 33 | bus.write_byte(address, 1 if status else 0) 34 | print "Arduino answer to RPI:", bus.read_byte(address) 35 | time.sleep(1) 36 | 37 | 38 | if __name__ == '__main__': 39 | try: 40 | main() 41 | except KeyboardInterrupt: 42 | print 'Interrupted' 43 | gpio.cleanup() 44 | sys.exit(0) 45 | 46 | ``` 47 | 48 | And finally the Arduino program. Arduino also answers to Raspberry pi with the value that it's been sent, and Raspberry Pi will log the answer within console 49 | 50 | ```c 51 | #include 52 | 53 | #define SLAVE_ADDRESS 0x04 54 | #define LED 13 55 | 56 | int number = 0; 57 | 58 | void setup() { 59 | pinMode(LED, OUTPUT); 60 | Serial.begin(9600); 61 | Wire.begin(SLAVE_ADDRESS); 62 | Wire.onReceive(receiveData); 63 | Wire.onRequest(sendData); 64 | 65 | Serial.println("Ready!"); 66 | } 67 | 68 | void loop() { 69 | delay(100); 70 | } 71 | 72 | void receiveData(int byteCount) { 73 | Serial.print("receiveData"); 74 | while (Wire.available()) { 75 | number = Wire.read(); 76 | Serial.print("data received: "); 77 | Serial.println(number); 78 | 79 | if (number == 1) { 80 | Serial.println(" LED ON"); 81 | digitalWrite(LED, HIGH); 82 | } else { 83 | Serial.println(" LED OFF"); 84 | digitalWrite(LED, LOW); 85 | } 86 | } 87 | } 88 | 89 | void sendData() { 90 | Wire.write(number); 91 | } 92 | ``` 93 | 94 | # Hardware: 95 | * Arduino UNO (https://www.arduino.cc/en/Main/ArduinoBoardUno) 96 | * Raspberry Pi 97 | * Two LEDs and two resistors 98 | 99 | # Demo 100 | [![Arduino and Raspberry Pi via i2c](http://img.youtube.com/vi/EMunlSg77DA/0.jpg)](https://www.youtube.com/watch?v=EMunlSg77DA) 101 | # References: 102 | https://oscarliang.com/raspberry-pi-arduino-connected-i2c 103 | http://www.electroensaimada.com/i2c.html 104 | --------------------------------------------------------------------------------