This page describes experiments in communicating between a [Raspberry Pi] (as a master) and an [Arduino] (as a slave) over [I2C]. The Raspberry Pi is programmed in [Python], the Arduino using a sketch (the Arduino's own language). I based this experiment on an article found on ''The Robotics Back-End'' (see References below), but have modified it to use Python rather than C on the Raspberry Pi, since that's the main language I've been using to write the operating system of the [KR01] robot. Some of the ideas I found online tended to lock up the I2C bus or cause other kinds of problems. When I stumbled onto an example using the WiringPi library things seemed to even out. __WiringPi__ is a C++ library for communicating with a Raspberry Pi. It's been ported to Python as the [WiringPi-Python|https://github.com/WiringPi/WiringPi-Python] library. WiringPi (both C++ and Python versions) has an I2C class to provide communication over I2C. The basic API is as follows: {{{ class I2C(object): def setupInterface(self,*args): return wiringPiI2CSetupInterface(*args) def setup(self,*args): return wiringPiI2CSetup(*args) def read(self,*args): return wiringPiI2CRead(*args) def readReg8(self,*args): return wiringPiI2CReadReg8(*args) def readReg16(self,*args): return wiringPiI2CReadReg16(*args) def write(self,*args): return wiringPiI2CWrite(*args) def writeReg8(self,*args): return wiringPiI2CWriteReg8(*args) def writeReg16(self,*args): return wiringPiI2CWriteReg16(*args) }}} In particular, we can expect to be using the {{wiringPiI2CRead()}} and {{wiringPiI2CWrite()}} methods. For documentation, see [The I2C Reference Library|http://wiringpi.com/reference/i2c-library/]. It should be noted that the I2C read and write methods send a single integer. In order to communicate strings or other data, you'll need to serialise the data and then deserialise it on the other end. For an example, see: [How do I serialize a Python dictionary into a string, and then back to a dictionary?|https://stackoverflow.com/questions/4342176/how-do-i-serialize-a-python-dictionary-into-a-string-and-then-back-to-a-diction] !! Raspberry Pi Installation WiringPi for Python can be installed via: {{{ sudo pip3 install wiringpi }}} !! Arduino Installation You'll need to install an Arduino sketch on your Arduino using the Arduino IDE. As an example, I modified the original source to blink the Arduino's built-in LEDs when either a transmit (TX) or receive (RX) event occurs. %%pre-scrollable {{{ #include <Wire.h> #define SLAVE_ADDRESS 0x08 byte data_to_echo = 0; // this slave code is meant to work on I2C address 0x08 // with rpi_arduino_wiringpi_i2c.cpp as described at: // https://roboticsbackend.com/raspberry-pi-master-arduino-slave-i2c-communication-with-wiringpi/ void setup() { Wire.begin(SLAVE_ADDRESS); Wire.onReceive(receiveData); Wire.onRequest(sendData); ready_blink(); } void loop() { } void receiveData(int bytecount) { for (int i = 0; i < bytecount; i++) { data_to_echo = Wire.read(); } blink_rx(); } void sendData() { Wire.write(data_to_echo); blink_tx(); } // status displays ..................................................... void ready_blink() { int i = 0; while ( i < 800 ) { blink_builtin(); delay(i); i = i + 50; } } void blink_builtin() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(100); // wait 100ms digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW } void blink_tx() { digitalWrite(LED_BUILTIN_TX, HIGH); // turn the LED on (HIGH is the voltage level) delay(100); // wait 100ms digitalWrite(LED_BUILTIN_TX, LOW); // turn the LED off by making the voltage LOW } void blink_rx() { digitalWrite(LED_BUILTIN_RX, HIGH); // turn the LED on (HIGH is the voltage level) delay(100); // wait 100ms digitalWrite(LED_BUILTIN_RX, LOW); // turn the LED off by making the voltage LOW } }}} %% !! References * [WiringPi|http://wiringpi.com/] (C++ library) * [WiringPi-Python|https://github.com/WiringPi/WiringPi-Python] on github * [Raspberry Pi (master) Arduino (slave) I2C communication with WiringPi|https://roboticsbackend.com/raspberry-pi-master-arduino-slave-i2c-communication-with-wiringpi/] * From Raspi.TV an article on __WiringPi2__ (really only the first is relevant here): ** [How to use WiringPi2 for Python on the Raspberry Pi in Raspbian part 1|https://raspi.tv/2013/how-to-use-wiringpi2-for-python-on-the-raspberry-pi-in-raspbian] ** [How to use WiringPi2 for Python with pull-ups or pull-downs and PWM – pt 2|https://raspi.tv/2013/how-to-use-wiringpi2-for-python-with-pull-ups-or-pull-downs-and-pwm] ** [Using the MCP23017 port expander with WiringPi2 to give you 16 new GPIO ports – part 3|https://raspi.tv/2013/using-the-mcp23017-port-expander-with-wiringpi2-to-give-you-16-new-gpio-ports-part-3] * [i2c SLAVE|https://github.com/adafruit/circuitpython/issues/437] on Adafruit's CircuitPython forum * [Raspberry Pi - Arduino Serial Communication|https://www.instructables.com/id/Raspberry-Pi-Arduino-Serial-Communication/] ---- [{Tag RaspberryPi Arduino}]