{"id":11708,"date":"2021-05-29T11:20:59","date_gmt":"2021-05-29T11:20:59","guid":{"rendered":"https:\/\/wolles-elektronikkiste.de\/how-to-use-the-i2c-interfaces-of-the-esp32"},"modified":"2021-05-29T11:21:02","modified_gmt":"2021-05-29T11:21:02","slug":"how-to-use-the-i2c-interfaces-of-the-esp32","status":"publish","type":"post","link":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32","title":{"rendered":"How to use the I2C interfaces of the ESP32"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">About this post<\/h2>\n\n<p>In my <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/tca9548a-i2c-multiplexer\" target=\"_blank\" rel=\"noopener\">last post,<\/a> I reported on how you use the TCA9548A or simple MOSFETs to control multiple devices with the same I2C address. In this article, I&#8217;ll stick to the topic and show you how to use the I2C interfaces of the ESP32. You may also be able to avoid address conflicts this way. This article is not an introduction to the ESP32. I will catch up on this in a separate post. So, I assume you&#8217;ve already integrated the ESP32 into your development environment.<\/p>\n<p>Another point that I am particularly concerned about in the article is the options of passing objects to functions or other objects.<\/p>\n\n<h2 class=\"wp-block-heading\">I2C interfaces of the ESP32<\/h2>\n\n<p>There are a number of different ESP32 boards available. However, the I2C interfaces of the ESP32 are organized in the same way for all versions (that I am aware of!). The default interface is located at pins 21 (SDA) and 22 (SCL). It can also be assigned to other pins. The second interface is not predefined regarding the pins, i.e. you have to set them before you can use them.<\/p>\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/ESP32.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/ESP32-1024x526.jpg\" alt=\"The I2C interfaces of the ESP32 are located on pins 21 and 22 and \/ or on freely selectable pins.\" class=\"wp-image-11612\" width=\"768\" height=\"395\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/ESP32-1024x526.jpg 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/ESP32-300x154.jpg 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/ESP32-768x394.jpg 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/ESP32-1536x788.jpg 1536w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/ESP32-2048x1051.jpg 2048w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/ESP32-1320x677.jpg 1320w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/a><figcaption>The I2C interfaces of the ESP32 are located on pins 21 and 22 and \/ or on freely selectable pins.<\/figcaption><\/figure>\n<h2 class=\"wp-block-heading\">How to use the standard I2C interface <\/h2>\n\n<p>If you only use the default I2C interface, there is no big difference in handling to the Arduino or ESP8266 boards (e.g. <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/wemos-d1-mini-boards\" target=\"_blank\" rel=\"noopener\">Wemos<\/a> or <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/esp8266-esp-01-module\" target=\"_blank\" rel=\"noopener\">ESP-01<\/a>). In most cases, you will use a library for the controlled I2C part.<\/p>\n\n<p>As an example for an I2C device, I use the <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/ads1115-a-d-converter-with-amplifier\" target=\"_blank\" rel=\"noopener\">A\/D converter ADS1115<\/a>again. You don&#8217;t have to deal with it in depth to understand the post. Just note that this module requires some initial settings and then converts voltages that are attached to the A0 port. No pull-ups are required for the circuit, since the ADS1115 already provides them.<\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_standard.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"619\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_standard-1024x619.png\" alt=\"ADS1115 attached to the standard I2C interface of the ESP32\" class=\"wp-image-11616\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_standard-1024x619.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_standard-300x181.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_standard-768x464.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_standard.png 1237w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>ADS1115 attached to the standard I2C interface of the ESP32<\/figcaption><\/figure>\n<p>I use my library ADS1115_WE. The ADS1115 object adc is created with <code>ADS1115_WE adc = ADS1115_WE (ADS1115_I2C_ADDRESS)<\/code>. As usual, the I2C communication is initialized with <code>Wire.begin()<\/code>.<\/p>\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"1_ADS1115.ino \" data-enlighter-title=\"1_ADS1115.ino\">#include&lt;ADS1115_WE.h&gt; \n#include&lt;Wire.h&gt;\n#define ADS1115_I2C_ADDRESS  0x48\n\nADS1115_WE adc = ADS1115_WE(ADS1115_I2C_ADDRESS);\n\nvoid setup() {\n  Wire.begin();\n  Serial.begin(9600); \n  setupAdc();\n}\n\nvoid loop() {\n  float voltage = 0.0;\n  \n  voltage = adc.getResult_V();\n  Serial.print(\"Voltage [V]: \");\n  Serial.println(voltage);\n\n  Serial.println(\"*********************************\");  \n  delay(1000);\n}\n\nvoid setupAdc(){\n  if(!adc.init()){\n      Serial.print(\"ADS1115 not connected!\");\n    }\n    adc.setVoltageRange_mV(ADS1115_RANGE_6144);\n    adc.setCompareChannels(ADS1115_COMP_0_GND);\n    adc.setMeasureMode(ADS1115_CONTINUOUS); \n}<\/pre>\n<p>&nbsp;<\/p>\n\n<h2 class=\"wp-block-heading\">How to use the two I2C interfaces of the ESP32<\/h2>\n\n<h3 class=\"wp-block-heading\">Variant 1: Define two interfaces<\/h3>\n\n<p>If you want to use both I2C interfaces of the ESP32, you first have to choose two SDA and two SCL pins. They are freely selectable. My choice fell on pins 15, 16, 17 and 18. The wiring of two ADS1115 is not surprising:<\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_I2C_1_2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"561\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_I2C_1_2-1024x561.png\" alt=\"Two ADS1115 attached to freely selected I2C pins\" class=\"wp-image-11619\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_I2C_1_2-1024x561.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_I2C_1_2-300x164.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_I2C_1_2-768x420.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_I2C_1_2-1320x723.png 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_I2C_1_2.png 1518w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>Two ADS1115 attached to freely selected I2C pins<\/figcaption><\/figure>\n<p>For programming you need to know that Wire is an object of the TwoWire class. You don&#8217;t usually care, because the object Wire is created with the inclusion of Wire.h. In the first example, instead of wire, we use two self-created objects that we call I2C_1 and I2C_2:<\/p>\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">TwoWire I2C_1 = TwoWire(0);\nTwoWire I2C_2 = TwoWire(1); <\/pre>\n\n<p>Before you say: Super, then I can create more TwoWire objects (<code>TwoWire I2C_3 = TwoWire(2)<\/code>, etc.) according to this scheme, I have to disappoint you. That doesn&#8217;t work. Only 0 and 1 work.<\/p>\n<p>Then you have to assign the SDA and SCL pins to I2C_1 and I2C_2. You do this by calling the <code>begin()<\/code> function. Optionally, you can pass the I2C frequency. This is what it looks like:<\/p>\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#define SDA_1 15\n#define SCL_1 16\n#define SDA_2 17\n#define SCL_2 18\n#define I2C_FREQ 400000\n....\n....\nI2C_1.begin(SDA_1, SCL_1, I2C_FREQ);\nI2C_2.begin(SDA_2, SCL_2, I2C_FREQ);<\/pre>\n\n<p>Now you have to assign the I2C interfaces to the objects of your I2C device (which is not supported by every library!). To do this you pass I2C_1 and I2C_2. Depending on the library, this usually has to be done when you initialize the object or with functions like <code>begin()<\/code> or <code>init()<\/code>. In most cases, example sketches of the libraries explain the procedure. For the ADS1115_WE library, passing the TwoWire object looks like this:<\/p>\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ADS1115_WE adc_1 = ADS1115_WE(&amp;I2C_1, ADS1115_I2C_ADDRESS); \nADS1115_WE adc_2 = ADS1115_WE(&amp;I2C_2, ADS1115_I2C_ADDRESS);<\/pre>\n\n<p style=\"text-align: left;\">A TwoWire object has a significant size. Therefore, to save memory space, most libraries do not work with local copies of the objects, but with the objects themselves. For this purpose, the TwoWire object is passed as a pointer, i.e. the receiving function uses pointers as parameters. In the function call I2C_1 and I2C_2 must be preceded by the address operator &#8220;&amp;&#8221;. If you don&#8217;t have any experience with it, it&#8217;s certainly confusing at first. I will come back to that further down.<\/p>\n<p>And this is what the complete sketch looks like:<\/p>\n\n<div class=\"scroll-paragraph-long\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"2_ADS1115.ino\" data-enlighter-title=\"2_ADS1115.ino\">#include&lt;ADS1115_WE.h&gt; \n#include&lt;Wire.h&gt;\n#define ADS1115_I2C_ADDRESS  0x48\n#define I2C_FREQ 400000\n\n#define SDA_1 15\n#define SCL_1 16\n#define SDA_2 17\n#define SCL_2 18\n\nTwoWire I2C_1 = TwoWire(0);\nTwoWire I2C_2 = TwoWire(1);\n\nADS1115_WE adc_1 = ADS1115_WE(&amp;I2C_1, ADS1115_I2C_ADDRESS);\nADS1115_WE adc_2 = ADS1115_WE(&amp;I2C_2, ADS1115_I2C_ADDRESS);\n\nvoid setup() {\n  Serial.begin(9600);\n  \n  I2C_1.begin(SDA_1, SCL_1, I2C_FREQ);\n  I2C_2.begin(SDA_2, SCL_2, I2C_FREQ);\n  \n  setupAdc_1();\n  setupAdc_2();\n}\n\nvoid loop() {\n  float voltage = 0.0;\n  \n  voltage = adc_1.getResult_V();\n  Serial.print(\"Voltage [V], ADS1115 No 1: \");\n  Serial.println(voltage);\n\n  voltage = adc_2.getResult_V();\n  Serial.print(\"Voltage [V], ADS1115 No 2: \");\n  Serial.println(voltage);\n  \n  Serial.println(\"*********************************\");  \n  delay(1000);\n}\n\nvoid setupAdc_1(){\n  if(!adc_1.init()){\n    Serial.println(\"ADS1115 No 1 not connected!\");\n  }\n  adc_1.setVoltageRange_mV(ADS1115_RANGE_6144);\n  adc_1.setCompareChannels(ADS1115_COMP_0_GND);\n  adc_1.setMeasureMode(ADS1115_CONTINUOUS); \n}\n\nvoid setupAdc_2(){\n  if(!adc_2.init()){\n    Serial.println(\"ADS1115 No 2 not connected!\");\n  }\n  adc_2.setVoltageRange_mV(ADS1115_RANGE_6144);\n  adc_2.setCompareChannels(ADS1115_COMP_0_GND);\n  adc_2.setMeasureMode(ADS1115_CONTINUOUS); \n}<\/pre>\n<\/div>\n\n<p>The code can be shortened because there are some identical function calls for adc_1 and adc_2. Thus, I introduce functions to which I pass these objects. Again, I don&#8217;t work with local copies of the objects, but with the originals. However, here I choose a different method to achieve this, namely using references as parameters. In the function call, for example: <\/p>\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">setupAdc(adc_1, 1);<\/pre>\n\n<p>the use of references is not visible. However, in the function itself you can see the difference, and that is the address operator:<\/p>\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void setupAdc(ADS1115_WE &amp;adc, byte i)<\/pre>\n<p>This introduces only another identifier for the object within the function.<\/p>\n\n<div class=\"scroll-paragraph-long\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"2_ADS1115_short.ino\" data-enlighter-title=\"2_ADS1115_short.ino\">#include&lt;ADS1115_WE.h&gt; \n#include&lt;Wire.h&gt;\n#define ADS1115_I2C_ADDRESS  0x48\n#define I2C_FREQ 400000\n\n#define SDA_1 15\n#define SCL_1 16\n#define SDA_2 17\n#define SCL_2 18\n\nTwoWire I2C_1 = TwoWire(0);\nTwoWire I2C_2 = TwoWire(1);\nADS1115_WE adc_1 = ADS1115_WE(&amp;I2C_1, ADS1115_I2C_ADDRESS);\nADS1115_WE adc_2 = ADS1115_WE(&amp;I2C_2, ADS1115_I2C_ADDRESS);\n\nvoid setup() {\n  Serial.begin(9600);\n  \n  I2C_1.begin(SDA_1, SCL_1, I2C_FREQ);\n  I2C_2.begin(SDA_2, SCL_2, I2C_FREQ);\n  \n  setupAdc(adc_1, 1);\n  setupAdc(adc_2, 2);\n}\n\nvoid loop() {\n  queryAdc(adc_1, 1);\n  queryAdc(adc_2, 2);\n  \n  Serial.println(\"*********************************\");  \n  delay(1000);\n}\n\nvoid setupAdc(ADS1115_WE &amp;adc, byte i){\n  if(!adc.init()){\n    Serial.print(\"ADS1115 No \");\n    Serial.print(i);\n    Serial.println(\" not connected!\");\n  }\n  adc.setVoltageRange_mV(ADS1115_RANGE_6144);\n  adc.setCompareChannels(ADS1115_COMP_0_GND);\n  adc.setMeasureMode(ADS1115_CONTINUOUS); \n}\n\nvoid queryAdc(ADS1115_WE &amp;adc, byte i){\n  float voltage = 0.0;\n  \n  voltage = adc.getResult_V();\n  Serial.print(\"Voltage [V], ADS1115 No \");\n  Serial.print(i);\n  Serial.print(\": \");\n  Serial.println(voltage);\n}<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n\n<h3 class=\"wp-block-heading\">Variant 2: Use of Wire and an additional interface<\/h3>\n\n<p>Not because it would have advantages, but for completeness I would like to show that you can also use the predefined Wire object and an additionally created TwoWire object. Compared to the last circuit, only the I2C pins change:<\/p>\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_wire_wire1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_wire_wire1-1024x563.png\" alt=\"Two ADS1115 attached the default Wire and an additional I2C interface\" class=\"wp-image-11629\" width=\"840\" height=\"461\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_wire_wire1-1024x563.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_wire_wire1-300x165.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_wire_wire1-768x422.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_wire_wire1-1320x726.png 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_esp32_wire_wire1.png 1513w\" sizes=\"auto, (max-width: 840px) 100vw, 840px\" \/><\/a><figcaption>Two ADS1115 attached the default Wire and an additional I2C interface<\/figcaption><\/figure>\n<p>I have called the additional TwoWire object Wire1. It must be created with <code>TwoWire(1)<\/code>. In some places I have read that Wire1 is also predefined just like Wire. But without <code>TwoWire Wire1 = TwoWire(1);<\/code> it didn&#8217;t work for me.<\/p>\n<p>Here&#8217;s what the sketch looks like:<\/p>\n\n<div class=\"scroll-paragraph-long\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"2_ADS1115_wire_wire1.ino\" data-enlighter-title=\"2_ADS1115_wire_wire1.ino\">#include&lt;ADS1115_WE.h&gt; \n#include&lt;Wire.h&gt;\n#define ADS1115_I2C_ADDRESS  0x48\n#define I2C_FREQ 400000\n#define SDA_2 17\n#define SCL_2 18\n\nTwoWire Wire1 = TwoWire(1);\n\nADS1115_WE adc_1 = ADS1115_WE(ADS1115_I2C_ADDRESS);\nADS1115_WE adc_2 = ADS1115_WE(&amp;Wire1, ADS1115_I2C_ADDRESS);\n\nvoid setup() {\n  Serial.begin(9600);\n  \n  Wire.begin();\n  Wire1.begin(SDA_2, SCL_2, I2C_FREQ);\n    \n  setupAdc(adc_1, 1);\n  setupAdc(adc_2, 2);\n}\n\nvoid loop() {\n  queryAdc(adc_1, 1);\n  queryAdc(adc_2, 2);\n  Serial.println(\"*********************************\");  \n  delay(1000);\n}\n\nvoid setupAdc(ADS1115_WE &amp;adc, byte i){\n  if(!adc.init()){\n      Serial.print(\"ADS1115 No \");\n      Serial.print(i);\n      Serial.println(\" not connected!\");\n    }\n    adc.setVoltageRange_mV(ADS1115_RANGE_6144);\n    adc.setCompareChannels(ADS1115_COMP_0_GND);\n    adc.setMeasureMode(ADS1115_CONTINUOUS); \n}\n\nvoid queryAdc(ADS1115_WE &amp;adc, byte i){\n  float voltage = 0.0;\n  \n  voltage = adc.getResult_V();\n  Serial.print(\"Voltage [V], ADS1115 No \");\n  Serial.print(i);\n  Serial.print(\": \");\n  Serial.println(voltage);\n}<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n\n<h2 class=\"wp-block-heading\">How to use I2C interfaces of the ESP32 without libraries <\/h2>\n\n<p>In previous examples, the I2C device was defined as an object via a library. If you work without a library, things are easier. Nevertheless, I will show an example using the I2C multiplexer TCA9548A because with this, I can explain the passing of pointers in more detail.<\/p>\n<p>I chose the TCA9548A because it allows you to control additional I2C devices with the same address. So, we&#8217;ll stay on topic. In addition, in terms of control, it is the simplest I2C device I could find.<\/p>\n<p>Since I covered the TCA9548A in my last post, I describe it here only roughly: The TCA9548A has an I2C input and eight I2C outputs. The channels are turned on and off by setting or deleting the corresponding bit in the control register. In this way, eight I2C components with the same address can be controlled addressed with one TCA9548A.<\/p>\n<p>This is what it looks like when you connect two TCA9548A to the ESP32:<\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_2_TCA9548A.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"474\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_2_TCA9548A-1024x474.png\" alt=\"Two TCA9548A connected to an ESP32\" class=\"wp-image-11634\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_2_TCA9548A-1024x474.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_2_TCA9548A-300x139.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_2_TCA9548A-768x356.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_2_TCA9548A-1320x611.png 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/wiring_2_TCA9548A.png 1389w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>Two TCA9548A connected to an ESP32<\/figcaption><\/figure>\n<p>The following sketch turns on channel 3 of one module and channel 7 of the other:<\/p>\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#include&lt;Wire.h&gt;\n#define TCA_I2C_ADDRESS  0x70\n#define TCA_1_CHANNEL  3\n#define TCA_2_CHANNEL  7\n#define I2C_FREQ_1 400000\n#define I2C_FREQ_2 400000\n\n#define SDA_1 15\n#define SCL_1 16\n#define SDA_2 17\n#define SCL_2 18\n\nTwoWire I2C_1 = TwoWire(0);\nTwoWire I2C_2 = TwoWire(1);\n\nvoid setup() {\n  I2C_1.begin(SDA_1, SCL_1, I2C_FREQ_1);\n  I2C_2.begin(SDA_2, SCL_2, I2C_FREQ_2);\n  setTCAChannel_1(TCA_1_CHANNEL);\n  setTCAChannel_2(TCA_2_CHANNEL);\n}\n\nvoid loop() { \n}\n\nvoid setTCAChannel_1(byte i){\n  I2C_1.beginTransmission(TCA_I2C_ADDRESS);\n  I2C_1.write(1 &lt;&lt; i);\n  I2C_1.endTransmission();  \n}\n\nvoid setTCAChannel_2(byte i){\n  I2C_2.beginTransmission(TCA_I2C_ADDRESS);\n  I2C_2.write(1 &lt;&lt; i);\n  I2C_2.endTransmission();  \n}<\/pre>\n<p>The two setTCAChannel() functions can be merged by passing the TwoWire object as a reference:<\/p>\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void setTCAChannel(byte i, TwoWire &amp;I2C){\n  I2C.beginTransmission(TCA_I2C_ADDRESS);\n  I2C.write(1 &lt;&lt; i);\n  I2C.endTransmission();  \n}<\/pre>\n<p>&nbsp;<\/p>\n\n<h4 class=\"wp-block-heading\">How to pass pointers<\/h4>\n\n<p>However, there is another method, namely passing the objects as pointers. The receiving function looks as follows:<\/p>\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void setTCAChannel(byte i, TwoWire *I2C){\n  TwoWire *wire = I2C;\n  wire-&gt;beginTransmission(TCA_I2C_ADDRESS);\n  wire-&gt;write(1 &lt;&lt; i);\n  wire-&gt;endTransmission();  \n}<\/pre>\n\n<p>Passing the object as a pointer has two consequences:<\/p>\n<ol>\n<li>You cannot apply the point operator to pointers. If you want to use a function of the object to which the pointer points, the equivalent is the arrow operator.<\/li>\n<li>When calling the above function, the object to be passed must be preceded by the address operator.<\/li>\n<\/ol>\n<p>And why do I tell all this? Because passing the TwoWire object works this way with most libraries and I can best show it in such a simple example.<\/p>\n<p>The full sketch looks like this:<\/p>\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">#include&lt;Wire.h&gt;\n#define TCA_I2C_ADDRESS  0x70\n#define TCA_1_CHANNEL  3\n#define TCA_2_CHANNEL  7\n#define I2C_FREQ_1 400000\n#define I2C_FREQ_2 400000\n\n#define SDA_1 15\n#define SCL_1 16\n#define SDA_2 17\n#define SCL_2 18\n\nTwoWire I2C_1 = TwoWire(0);\nTwoWire I2C_2 = TwoWire(1);\n\nvoid setup() {\n  I2C_1.begin(SDA_1, SCL_1, I2C_FREQ_1);\n  I2C_2.begin(SDA_2, SCL_2, I2C_FREQ_2);\n  setTCAChannel(TCA_1_CHANNEL, &amp;I2C_1);\n  setTCAChannel(TCA_2_CHANNEL, &amp;I2C_2);\n}\n\nvoid loop() { \n}\n\nvoid setTCAChannel(byte i, TwoWire *I2C){\n  TwoWire *wire = I2C;\n  wire-&gt;beginTransmission(TCA_I2C_ADDRESS);\n  wire-&gt;write(1 &lt;&lt; i);\n  wire-&gt;endTransmission();  \n}<\/pre>\n<p>&nbsp;<\/p>\n\n<h2 class=\"wp-block-heading\">Update of my libraries<\/h2>\n\n<p>I&#8217;ve published a number of libraries on GitHub. With one exception, I&#8217;ve revised them over the last few weeks to allow TwoWire objects to be passed as an option. You find the libraries <a href=\"https:\/\/github.com\/wollewald?tab=repositories\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n\n<h2 class=\"wp-block-heading\">Acknowledgement<\/h2>\n\n<p>I found the Fritzing component for the ESP32 <a href=\"https:\/\/forum.fritzing.org\/t\/esp32s-hiletgo-dev-boad-with-pinout-template\/5357\" target=\"_blank\" rel=\"noopener\">here<\/a> in the Fritzing Forum. Thanks to the designers.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I will show you how to use the two I2C interfaces of the ESP32 and which requirements libraries of I2C components must have for this. <\/p>\n","protected":false},"author":1,"featured_media":11703,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[543],"tags":[1044,666,1443,1444,1445,1446],"class_list":["post-11708","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-boards-and-microcontrollers","tag-esp32-en","tag-i2c-en","tag-twowire-en","tag-twowire0-en","tag-twowire1-en","tag-wire1-en"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>How to use the I2C interfaces of the ESP32 &#8226; Wolles Elektronikkiste<\/title>\n<meta name=\"description\" content=\"I will show you how to use the two I2C interfaces of the ESP32 and which requirements libraries of I2C components must have for this.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to use the I2C interfaces of the ESP32 &#8226; Wolles Elektronikkiste\" \/>\n<meta property=\"og:description\" content=\"I will show you how to use the two I2C interfaces of the ESP32 and which requirements libraries of I2C components must have for this.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32\" \/>\n<meta property=\"og:site_name\" content=\"Wolles Elektronikkiste\" \/>\n<meta property=\"article:published_time\" content=\"2021-05-29T11:20:59+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-05-29T11:21:02+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/Beitragsbild_ESP32_I2C.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"1186\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Wolfgang Ewald\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Wolfgang Ewald\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32\"},\"author\":{\"name\":\"Wolfgang Ewald\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"headline\":\"How to use the I2C interfaces of the ESP32\",\"datePublished\":\"2021-05-29T11:20:59+00:00\",\"dateModified\":\"2021-05-29T11:21:02+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32\"},\"wordCount\":1299,\"commentCount\":23,\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/Beitragsbild_ESP32_I2C.png\",\"keywords\":[\"ESP32\",\"I2C\",\"TwoWire\",\"TwoWire(0)\",\"TwoWire(1)\",\"Wire1\"],\"articleSection\":[\"Boards and Microcontrollers\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32\",\"name\":\"How to use the I2C interfaces of the ESP32 &#8226; Wolles Elektronikkiste\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/Beitragsbild_ESP32_I2C.png\",\"datePublished\":\"2021-05-29T11:20:59+00:00\",\"dateModified\":\"2021-05-29T11:21:02+00:00\",\"description\":\"I will show you how to use the two I2C interfaces of the ESP32 and which requirements libraries of I2C components must have for this.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32#primaryimage\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/Beitragsbild_ESP32_I2C.png\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/Beitragsbild_ESP32_I2C.png\",\"width\":1200,\"height\":1186},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/how-to-use-the-i2c-interfaces-of-the-esp32#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to use the I2C interfaces of the ESP32\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\",\"name\":\"Wolles Elektronikkiste\",\"description\":\"Die wunderbare Welt der Elektronik\",\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\",\"name\":\"Wolfgang Ewald\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"width\":512,\"height\":512,\"caption\":\"Wolfgang Ewald\"},\"logo\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to use the I2C interfaces of the ESP32 &#8226; Wolles Elektronikkiste","description":"I will show you how to use the two I2C interfaces of the ESP32 and which requirements libraries of I2C components must have for this.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32","og_locale":"en_US","og_type":"article","og_title":"How to use the I2C interfaces of the ESP32 &#8226; Wolles Elektronikkiste","og_description":"I will show you how to use the two I2C interfaces of the ESP32 and which requirements libraries of I2C components must have for this.","og_url":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32","og_site_name":"Wolles Elektronikkiste","article_published_time":"2021-05-29T11:20:59+00:00","article_modified_time":"2021-05-29T11:21:02+00:00","og_image":[{"width":1200,"height":1186,"url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/Beitragsbild_ESP32_I2C.png","type":"image\/png"}],"author":"Wolfgang Ewald","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Wolfgang Ewald","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32#article","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32"},"author":{"name":"Wolfgang Ewald","@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"headline":"How to use the I2C interfaces of the ESP32","datePublished":"2021-05-29T11:20:59+00:00","dateModified":"2021-05-29T11:21:02+00:00","mainEntityOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32"},"wordCount":1299,"commentCount":23,"publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/Beitragsbild_ESP32_I2C.png","keywords":["ESP32","I2C","TwoWire","TwoWire(0)","TwoWire(1)","Wire1"],"articleSection":["Boards and Microcontrollers"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32","url":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32","name":"How to use the I2C interfaces of the ESP32 &#8226; Wolles Elektronikkiste","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#website"},"primaryImageOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32#primaryimage"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/Beitragsbild_ESP32_I2C.png","datePublished":"2021-05-29T11:20:59+00:00","dateModified":"2021-05-29T11:21:02+00:00","description":"I will show you how to use the two I2C interfaces of the ESP32 and which requirements libraries of I2C components must have for this.","breadcrumb":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32#primaryimage","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/Beitragsbild_ESP32_I2C.png","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/05\/Beitragsbild_ESP32_I2C.png","width":1200,"height":1186},{"@type":"BreadcrumbList","@id":"https:\/\/wolles-elektronikkiste.de\/en\/how-to-use-the-i2c-interfaces-of-the-esp32#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/wolles-elektronikkiste.de\/en"},{"@type":"ListItem","position":2,"name":"How to use the I2C interfaces of the ESP32"}]},{"@type":"WebSite","@id":"https:\/\/wolles-elektronikkiste.de\/en#website","url":"https:\/\/wolles-elektronikkiste.de\/en","name":"Wolles Elektronikkiste","description":"Die wunderbare Welt der Elektronik","publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wolles-elektronikkiste.de\/en?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46","name":"Wolfgang Ewald","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","width":512,"height":512,"caption":"Wolfgang Ewald"},"logo":{"@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png"}}]}},"_links":{"self":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/11708","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/comments?post=11708"}],"version-history":[{"count":0,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/11708\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media\/11703"}],"wp:attachment":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media?parent=11708"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/categories?post=11708"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/tags?post=11708"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}