{"id":155800,"date":"2024-06-20T11:35:29","date_gmt":"2024-06-20T11:35:29","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=155800"},"modified":"2024-06-20T13:57:31","modified_gmt":"2024-06-20T13:57:31","slug":"esp32-i2c-master-slave-arduino","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-i2c-master-slave-arduino\/","title":{"rendered":"ESP32 I2C Master and Slave (I2C Communication Between Two ESP32) &#8211; Arduino IDE"},"content":{"rendered":"\n<p>In this guide, you&#8217;ll learn how to exchange data between two ESP32 boards using I2C communication protocol. One ESP32 board will be set as an I2C master and the other board as an I2C slave. The ESP32 boards will be programmed using Arduino IDE.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-Master-Slave.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 I2C Master and Slave I2C Communication Between Two ESP32 boards Arduino IDE\" class=\"wp-image-155840\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-Master-Slave.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-Master-Slave.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-Master-Slave.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-Master-Slave.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-Master-Slave.jpg?resize=1536%2C864&amp;quality=100&amp;strip=all&amp;ssl=1 1536w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p>Do you need a wireless communication protocol? <a href=\"https:\/\/randomnerdtutorials.com\/esp-now-esp32-arduino-ide\/\" title=\"\">Try ESP-NOW communication protocol with the ESP32 to exchange data between boards<\/a>.<\/p>\n\n\n\n<p><strong>Table of Contents<\/strong><\/p>\n\n\n\n<p>In this guide, we&#8217;ll cover the following topics:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#intro-i2c\" title=\"\">Introducing I2C<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#esp32-bus-interface\" title=\"\">ESP32 I2C Bus Interfaces<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#esp32-master-slave\" title=\"\">ESP32 Master and ESP32 Slave<\/a><\/li>\n\n\n\n<li><a href=\"#connect-esp32-i2c\" title=\"\">Connecting two ESP32 Boards via I2C<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#connect-esp32-i2c\" title=\"\">I2C Communication Between 2 ESP32 boards<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#esp32-slave-code\" title=\"\">ESP32 I2C Slave &#8211; Arduino Code<\/a><\/li>\n\n\n\n<li><a href=\"#esp32-master-code\" title=\"\">ESP32 I2C Master &#8211; Arduino Code<\/a><\/li>\n\n\n\n<li><a href=\"#demonstration\" title=\"\">Exchange Data Between Two ESP32 Boards via I2C &#8211; Demonstration<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"intro-i2c\">Introducing I2C<\/h2>\n\n\n\n<p>I\u00b2C means&nbsp;<strong>I<\/strong>nter&nbsp;<strong>I<\/strong>ntegrated&nbsp;<strong>C<\/strong>ircuit (it\u2019s pronounced I-squared-C), and it is a synchronous, multi-master, multi-slave communication protocol. You can connect :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Multiple slaves to one master:<\/strong>&nbsp;for example, your ESP32 reads from a BME280 sensor using I2C and writes the sensor readings in an I2C OLED display.<\/li>\n\n\n\n<li><strong>Multiple masters controlling the same slave:<\/strong>&nbsp;for example, two ESP32 boards writing data to the same I2C OLED display.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"esp32-bus-interface\">ESP32 I2C Bus Interfaces<\/h3>\n\n\n\n<p>The ESP32 supports I2C communication through its two I2C bus interfaces that can serve as I2C master or slave, depending on the user\u2019s configuration. Accordingly to the ESP32 datasheet, the I2C interfaces of the ESP32 supports:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Standard mode (100 Kbit\/s)&nbsp;<\/li>\n\n\n\n<li>Fast mode (400 Kbit\/s)&nbsp;<\/li>\n\n\n\n<li>Up to 5 MHz, yet constrained by SDA pull-up strength&nbsp;<\/li>\n\n\n\n<li>7-bit\/10-bit addressing mode&nbsp;<\/li>\n\n\n\n<li>Dual addressing mode. Users can program command registers to control I\u00b2C interfaces, so that they have more flexibility<\/li>\n<\/ul>\n\n\n\n<p>For a more detailed introduction to I2C communication with the ESP32, read our guide:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-i2c-communication-arduino-ide\/\" title=\"\">ESP32 I2C Communication: Set Pins, Multiple Bus Interfaces and Peripherals (Arduino IDE)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"esp32-master-slave\">ESP32 Master and ESP32 Slave<\/h2>\n\n\n\n<p>For I2C communication between two ESP32 boards, we&#8217;ll use<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The default <span class=\"rnthl rntliteral\">Wire.h<\/span> library<\/li>\n\n\n\n<li>The default I2C pins on both boards (these may vary depending on your board model)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"connect-esp32-i2c\">Connecting two ESP32 Boards via I2C<\/h2>\n\n\n\n<p>Start by connecting the two ESP32 boards with each other. Use the default I2C pins for the boards you&#8217;re using. Don&#8217;t forget to connect the GND pins together.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"1020\" height=\"822\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-master-slave_bb.png?resize=1020%2C822&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Connecting two ESP32 Boards via I2C master slave communication\" class=\"wp-image-155842\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-master-slave_bb.png?w=1020&amp;quality=100&amp;strip=all&amp;ssl=1 1020w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-master-slave_bb.png?resize=300%2C242&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-master-slave_bb.png?resize=768%2C619&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1020px) 100vw, 1020px\" \/><\/figure><\/div>\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>ESP32 Master<\/strong><\/td><td><strong>ESP32 Slave<\/strong><\/td><\/tr><tr><td><span class=\"rnthl rntclgray\">SDA<\/span> (GPIO 21)*<\/td><td><span class=\"rnthl rntclgray\">SDA<\/span>(GPIO 21)*<\/td><\/tr><tr><td><span class=\"rnthl rntcyellow\">SCL<\/span> (GPIO 22)*<\/td><td><span class=\"rnthl rntcyellow\">SCL<\/span> (GPIO 22)*<\/td><\/tr><tr><td><span class=\"rnthl rntcblack\">GND<\/span><\/td><td><span class=\"rnthl rntcblack\">GND<\/span><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>* in my case, I&#8217;m testing this with the ESP32 DOIT V1 board. The default I2C pins are GPIO <span class=\"rnthl rntclgray\">21 (SDA)<\/span> and <span class=\"rnthl rntcyellow\">GPIO 22 (SCL)<\/span>. If you&#8217;re using an ESP32-C3, ESP32-S3, or other model, the default I2C pins might be different. Please check the pinout for the board you&#8217;re using.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i2c-communication-two-esp32\">I2C Communication Between 2 ESP32 boards<\/h3>\n\n\n\n<p>Here&#8217;s how I2C communication between two ESP32 boards works:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>ESP32 Master<\/strong><\/td><td><strong>ESP32 Slave<\/strong><\/td><\/tr><tr><td><\/td><td>Sets its I2C address<br>Sets callback functions:<br>    &#8211; to read received messages;<br>    &#8211; to handle requests.<\/td><\/tr><tr><td>Initializes I2C bus on the slave I2C address<br>Starts I2C communication on the I2C bus<\/td><td><\/td><\/tr><tr><td>Sends a message via I2C (Starts transmission)<\/td><td><\/td><\/tr><tr><td><\/td><td>Reads the received message <\/td><\/tr><tr><td>Requests data from the slave<\/td><td><\/td><\/tr><tr><td><\/td><td>Sends data to the master<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"esp32-slave-code\">ESP32 I2C Slave &#8211; Arduino Code<\/h2>\n\n\n\n<p>To test setting the ESP32 as an I2C slave, we&#8217;ll use the default example from the <span class=\"rnthl rntliteral\">Wire.h<\/span> library.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-i2c-master-slave-arduino\/\n  ESP32 I2C Slave example: https:\/\/github.com\/espressif\/arduino-esp32\/blob\/master\/libraries\/Wire\/examples\/WireSlave\/WireSlave.ino\n*********\/\n\n#include &quot;Wire.h&quot;\n\n#define I2C_DEV_ADDR 0x55\n\nuint32_t i = 0;\n\nvoid onRequest() {\n  Wire.print(i++);\n  Wire.print(&quot; Packets.&quot;);\n  Serial.println(&quot;onRequest&quot;);\n  Serial.println();\n}\n\nvoid onReceive(int len) {\n  Serial.printf(&quot;onReceive[%d]: &quot;, len);\n  while (Wire.available()) {\n    Serial.write(Wire.read());\n  }\n  Serial.println();\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  Serial.setDebugOutput(true);\n  Wire.onReceive(onReceive);\n  Wire.onRequest(onRequest);\n  Wire.begin((uint8_t)I2C_DEV_ADDR);\n\n\/*#if CONFIG_IDF_TARGET_ESP32\n  char message[64];\n  snprintf(message, 64, &quot;%lu Packets.&quot;, i++);\n  Wire.slaveWrite((uint8_t *)message, strlen(message));\n  Serial.print('Printing config %lu', i);\n#endif*\/\n}\n\nvoid loop() {\n  \n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_I2C_Slave.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How does the code work?<\/h3>\n\n\n\n<p>Let&#8217;s take a quick look at how the slave code works.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Including the Wire Library<\/h4>\n\n\n\n<p>First, you need to include the <span class=\"rnthl rntliteral\">Wire.h<\/span> library.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include \"Wire.h\"<\/code><\/pre>\n\n\n\n<p>Define the I2C address you want to give to your I2C device. In this case, it&#8217;s <span class=\"rnthl rntliteral\">0x55<\/span>, but you can define any other address as long as you use the same one on the master device.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define I2C_DEV_ADDR 0x55<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Assign Callback Functions<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, you must assign two callback functions: one for when the board receives data from the master and another one for when the board receives a request from the master (send data to the master).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Wire.onReceive(onReceive);\nWire.onRequest(onRequest);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">onReceive() Callback Function<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">onReceive()<\/span> function will read the data sent from the master and prints it on the Serial monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void onReceive(int len) {\n  Serial.printf(\"onReceive&#091;%d]: \", len);\n  while (Wire.available()) {\n    Serial.write(Wire.read());\n  }\n  Serial.println();\n}<\/code><\/pre>\n\n\n\n<p>You check if there&#8217;s data available to read using <span class=\"rnthl rntliteral\">Wire.available()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>while (Wire.available()) {<\/code><\/pre>\n\n\n\n<p>Then, you read the received bytes with <span class=\"rnthl rntliteral\">Wire.read()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.write(Wire.read());<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">onRequest() Callback Function<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">onRequest()<\/span> function will send data to the Master when requested.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void onRequest() {\n  Wire.print(i++);\n  Wire.print(\" Packets.\");\n  Serial.println(\"onRequest\");\n  Serial.println();\n}<\/code><\/pre>\n\n\n\n<p>To send data to the master, we use <span class=\"rnthl rntliteral\">Wire.print()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Wire.print(i++);\nWire.print(\" Packets.\");<\/code><\/pre>\n\n\n\n<p>In the documentation, it mentions that you need to use <span class=\"rnthl rntliteral\">Wire.slaveWrite()<\/span> in the case of the ESP32, so that it writes the response to the buffer before receiving a message from the master. However, in our case, it works well without <span class=\"rnthl rntliteral\">Wire.slaveWrite()<\/span> (that&#8217;s why we have that section commented).<\/p>\n\n\n\n<p>Depending on your board, you may need to use the <span class=\"rnthl rntliteral\">slaveWrite()<\/span> method as follows.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/*#if CONFIG_IDF_TARGET_ESP32\n  char message&#091;64];\n  snprintf(message, 64, \"%lu Packets.\", i++);\n  Wire.slaveWrite((uint8_t *)message, strlen(message));\n  Serial.print('Printing config %lu', i);\n#endif*\/<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Initialize I2C<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, you must also initialize I2C communication on the I2C address defined earlier. Use the <span class=\"rnthl rntliteral\">begin()<\/span> method as follows. This will initialize I2C on the ESP32 default I2C pins.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Wire.begin((uint8_t)I2C_DEV_ADDR);<\/code><\/pre>\n\n\n\n<p>You can also pass the I2C pins and bus frequency to this method:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>bool Wire.begin(uint8_t <strong>addr<\/strong>, int <strong>sdaPin<\/strong>, int <strong>sclPin<\/strong>, uint32_t <strong>frequency<\/strong>);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"esp32-master-code\">ESP32 I2C Master &#8211; Arduino Code<\/h2>\n\n\n\n<p>To test setting the ESP32 as an I2C master, we&#8217;ll use the default example from the <span class=\"rnthl rntliteral\">Wire.h<\/span> library.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-i2c-master-slave-arduino\/\n  ESP32 I2C Master Example: https:\/\/github.com\/espressif\/arduino-esp32\/blob\/master\/libraries\/Wire\/examples\/WireMaster\/WireMaster.ino\n*********\/\n\n#include &quot;Wire.h&quot;\n\n#define I2C_DEV_ADDR 0x55\n\nuint32_t i = 0;\n\nvoid setup() {\n  Serial.begin(115200);\n  Serial.setDebugOutput(true);\n  Wire.begin();\n}\n\nvoid loop() {\n  delay(5000);\n\n  \/\/ Write message to the slave\n  Wire.beginTransmission(I2C_DEV_ADDR);\n  Wire.printf(&quot;Hello World! %lu&quot;, i++);\n  uint8_t error = Wire.endTransmission(true);\n  Serial.printf(&quot;endTransmission: %u\\n&quot;, error);\n\n  \/\/ Read 16 bytes from the slave\n  uint8_t bytesReceived = Wire.requestFrom(I2C_DEV_ADDR, 16);\n  \n  Serial.printf(&quot;requestFrom: %u\\n&quot;, bytesReceived);\n  if ((bool)bytesReceived) {  \/\/If received more than zero bytes\n    uint8_t temp[bytesReceived];\n    Wire.readBytes(temp, bytesReceived);\n    log_print_buf(temp, bytesReceived);\n  }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_I2C_Master.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How does the code work?<\/h3>\n\n\n\n<p>Let&#8217;s take a quick look at how the ESP32 I2C Master code works.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Including the Wire Library<\/h4>\n\n\n\n<p>First, you need to include the <span class=\"rnthl rntliteral\">Wire.h<\/span> library.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include \"Wire.h\"<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Slave I2C Address<\/h4>\n\n\n\n<p>Set the I2C address of the slave device (set on the previous code):<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define I2C_DEV_ADDR 0x55<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Initialize I2C<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, initialize I2C communication using <span class=\"rnthl rntliteral\">Wire.begin()<\/span>. This will initialize I2C on the default I2C pins.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Wire.begin();<\/code><\/pre>\n\n\n\n<p>You can also pass the I2C pins and bus frequency to this method:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>bool Wire.begin(uint8_t <strong>addr<\/strong>, int <strong>sdaPin<\/strong>, int <strong>sclPin<\/strong>, uint32_t <strong>frequency<\/strong>);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Start Communication with the Slave<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span>, we send a message to the slave to inform that we&#8217;ll start I2C transmission:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Write message to the slave\nWire.beginTransmission(I2C_DEV_ADDR);\nWire.printf(\"Hello World! %lu\", i++);\nuint8_t error = Wire.endTransmission(true);\nSerial.printf(\"endTransmission: %u\\n\", error);<\/code><\/pre>\n\n\n\n<p>First, you need to call the <span class=\"rnthl rntliteral\">beginTransmission()<\/span> method and pass the slave address before writing a message.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Wire.beginTransmission(I2C_DEV_ADDR);<\/code><\/pre>\n\n\n\n<p>Then, you write a message to the buffer using the <span class=\"rnthl rntliteral\">printf()<\/span> method.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.printf(\"endTransmission: %u\\n\", error);<\/code><\/pre>\n\n\n\n<p>Finally, to send the buffered message, you need to use the <span class=\"rnthl rntliteral\">endTransmission()<\/span> method.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>uint8_t error = Wire.endTransmission(true);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Request Data From the Slave<\/h4>\n\n\n\n<p>Then, we request data from the slave using <span class=\"rnthl rntliteral\">Wire.requestFrom()<\/span>. Pass as argument the address of the slave and the number of requested bytes.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Read 16 bytes from the slave\nuint8_t bytesReceived = Wire.requestFrom(I2C_DEV_ADDR, 16);<\/code><\/pre>\n\n\n\n<p>Then, concatenate all the bytes and print the received data.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.printf(\"requestFrom: %u\\n\", bytesReceived);\nif ((bool)bytesReceived) {  \/\/If received more than zero bytes\n  uint8_t temp&#091;bytesReceived];\n  Wire.readBytes(temp, bytesReceived);\n  log_print_buf(temp, bytesReceived);\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"demonstration\">Exchange Data Between Two ESP32 Boards via I2C &#8211; Demonstration<\/h2>\n\n\n\n<p>Upload the master and slave I2C sketches to your ESP32 boards. Open two instances of the Arduino IDE to see the Serial Monitor for both boards simultaneously.<\/p>\n\n\n\n<p>You should see the master initializing a communication with the slave and receiving the data packets.<\/p>\n\n\n\n<p>This is what you should get on the slave (a <span class=\"rnthl rntliteral\">Hello World message!<\/span> followed by a counter and the <span class=\"rnthl rntliteral\">onRequest<\/span> function being triggered):<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"380\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-i2c-slave-serial-monitor-f.png?resize=750%2C380&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Exchange Data Between Two ESP32 Boards via I2C Demonstration\" class=\"wp-image-155810\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-i2c-slave-serial-monitor-f.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-i2c-slave-serial-monitor-f.png?resize=300%2C152&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>On the Master, you&#8217;ll receive the packets sent from the slave.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"903\" height=\"374\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-i2c-master-serial-monitor-f.png?resize=903%2C374&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Exchange Data Between Two ESP32 Boards via I2C Demonstration Master Slave\" class=\"wp-image-155811\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-i2c-master-serial-monitor-f.png?w=903&amp;quality=100&amp;strip=all&amp;ssl=1 903w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-i2c-master-serial-monitor-f.png?resize=300%2C124&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-i2c-master-serial-monitor-f.png?resize=768%2C318&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 903px) 100vw, 903px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, we&#8217;ve shown you how to set the ESP32 as an I2C slave and as an I2C master and how to exchange data between two EPS32 boards using I2C communication protocol.<\/p>\n\n\n\n<p>For more details about using the <span class=\"rnthl rntliteral\">Wire<\/span> library for I2C communication, check the official documentation: <a href=\"https:\/\/espressif-docs.readthedocs-hosted.com\/projects\/arduino-esp32\/en\/latest\/api\/i2c.html#arduino-esp32-i2c-api\" target=\"_blank\" rel=\"noopener\" title=\"\">Arduino-ESP32 I2C API Documentation<\/a>.<\/p>\n\n\n\n<p>We have other I2C tutorials with the ESP32 that you may find useful:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-i2c-scanner-arduino\/\">ESP32: I2C Scanner (Arduino IDE) \u2013 Finding the Address of I2C Devices<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-i2c-communication-arduino-ide\/\">ESP32 I2C Communication: Set Pins, Multiple Bus Interfaces and Peripherals (Arduino IDE)<\/a><\/li>\n<\/ul>\n\n\n\n<p>If you want to exchange data between two ESP32 boards wirelessly, we recommend using ESP-NOW instead:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp-now-esp32-arduino-ide\/\" title=\"\">Getting Started with ESP-NOW (ESP32 with Arduino IDE)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp-now-two-way-communication-esp32\/\">ESP-NOW Two-Way Communication Between ESP32 Boards<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp-now-one-to-many-esp32-esp8266\/\">ESP-NOW with ESP32: Send Data to Multiple Boards (one-to-many)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp-now-many-to-one-esp32\/\">ESP-NOW with ESP32: Receive Data from Multiple Boards (many-to-one)<\/a><\/li>\n<\/ul>\n\n\n\n<p>We hope this tutorial is useful. Learn more about the ESP32 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE (2nd Edition)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/smart-home-ebook\/\">SMART HOME with Raspberry Pi, ESP32, ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/build-web-servers-esp32-esp8266-ebook\/\">Build Web Servers with ESP32 and ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/firebase-esp32-esp8266-ebook\/\">Firebase Web App with the ESP32 and ESP8266<\/a><\/li>\n\n\n\n<li><strong><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">Free ESP32 Projects, Tutorials and Guides<\/a><\/strong><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, you&#8217;ll learn how to exchange data between two ESP32 boards using I2C communication protocol. One ESP32 board will be set as an I2C master and the other &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 I2C Master and Slave (I2C Communication Between Two ESP32) &#8211; Arduino IDE\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-i2c-master-slave-arduino\/#more-155800\" aria-label=\"Read more about ESP32 I2C Master and Slave (I2C Communication Between Two ESP32) &#8211; Arduino IDE\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":155840,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,277,299,264],"tags":[],"class_list":["post-155800","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/05\/ESP32-I2C-Master-Slave.jpg?fit=1920%2C1080&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/155800","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=155800"}],"version-history":[{"count":16,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/155800\/revisions"}],"predecessor-version":[{"id":159365,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/155800\/revisions\/159365"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/155840"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=155800"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=155800"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=155800"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}