ESP32 I2C Issue: Interrupt wdt timeout on CPU0

Good morning,
im new to the topic of I2C, was reading a lot in the past and try to understand how it works. Maybe I made something wrong or misunderstood anything. I was starting step by step. My Master µC is an Espressif ESP32-S2 and I made different setups (short distances on breadboard):

  1. I2C Connection between ESP32-S2 and external real time clock (RTC): The SDA and SCA pins of the ESP32-S2 (Master device) are directly connected with the RTC DSB3231 (Slave). The RTC is power by 3.3V, GND is connected as well. At the clock board are already pullup resistors for SDA and SCL available (4.7kOhm each) so i had nothing to do here. I tested the connection and it works like charme.

  2. How cool would it be to communicate with an other ESP8266 instead of the RTC? It should be possible since core 2.5.0: Release 2.5.0 · esp8266/Arduino · GitHub. I was using this example code at the ESP8266 (Slave): Arduino/slave_receiver.ino at master · esp8266/Arduino · GitHub. At the master device, I was sending just random stuff and was checking the serial monitor of the slave device. Everything perfect. Everything is transmitted and received perfectly. Since the RTC was removed, I added one pullup resistor (2.4kOhm) for SDA and an other one for SCL.

  3. The last step was to connect all together. I removed the previous added 2.4 kOhm resistors because of the RTC board (which already have pullups) and was connecting all SDA and SCL lines together. My sketch for the master device is as simple as possible, the slave is still the same as before (just reading if there is income).

Short summary of the master device sketch: if the RTC (slave) is available, reading time, date and day of week of the RTC and store values to char array. This values are printed to the serial monitor of the master device. After that, just send random stuff to the ESP8266 (slave). I can check the received data with a second serial monitor at the slave device. This code is in a loop without delay and will be executed every second. And here is the code of the master device:

#include <Wire.h>
#include "DS3231_RTC.h"

#define SDA_PIN              8
#define SCL_PIN              9

#define RTC_ADDRESS       0x68
#define ESP8266_ADDRESS   0x08

DS3231_RTC rtc(RTC_ADDRESS);

unsigned long previousMillis = 0;
const long interval = 1000;

char rtc_time[6];
char rtc_date[9];
char rtc_dow[11];

int counter = 0;

void setup(){
  //Wire.setClock(100000L);
  Wire.begin(SDA_PIN, SCL_PIN);
  Serial.begin(115200);
}

void loop(){

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {

    previousMillis = currentMillis;

    if(rtc.available()){
      rtc.getTime(CLOCK, rtc_time);
      rtc.getDate(rtc_date);
      rtc.getDow(rtc_dow);

      Serial.print("Counter: "); Serial.println(counter);
      Serial.print("Time: "); Serial.println(rtc_time);
      Serial.print("Date: "); Serial.println(rtc_date);
      Serial.print("Day of week: "); Serial.println(rtc_dow);
      Serial.println();
    }

    Wire.beginTransmission(ESP8266_ADDRESS);
    Wire.write(0x11);   // Send random stuff
    Wire.write(0x89);
    Wire.write(0x38);
    Wire.write(0x12);  
    Wire.endTransmission();

    counter++;
  }
  
}

The connection between Master and RTC seems to be okay. I can read and print the values of the RTC. Sometimes there is a wrong value or nothing (RTC not available) but for the most of the time, it looks good. The connection between Master and ESP8266 is almost okay as well. Its the same as with the RTC, some values are sometimes not received.

But here is the point: The Master device ist crashing randomly. Sometimes after 1 minute, sometimes after 30 minutes, sometimes twice in a row… I get this message:

Guru Meditation Error: Core  0 panic'ed (Interrupt wdt timeout on CPU0). 

Core  0 register dump:
PC      : 0x4002a360  PS      : 0x00060034  A0      : 0x8002aa6d  A1      : 0x3ffbfa70  
A2      : 0x3ffcd96c  A3      : 0x00000001  A4      : 0x00060021  A5      : 0x3ffcd920  
A6      : 0x00000001  A7      : 0x00000000  A8      : 0x8002a360  A9      : 0x3ffbfa60  
A10     : 0x00060023  A11     : 0x00000003  A12     : 0x00060023  A13     : 0x3ffcd978  
A14     : 0x00000000  A15     : 0x00000000  SAR     : 0x0000001f  EXCCAUSE: 0x00000005  
EXCVADDR: 0x00000000  LBEG    : 0x00060023  LEND    : 0x3ffcd978  LCOUNT  : 0x40025ee0  
Core  0 was running in ISR context:
EPC1    : 0x4002a780  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x4002a360

Backtrace:0x4002a35d:0x3ffbfa70 0x4002aa6a:0x3ffbfa90 0x40026619:0x3ffbfac0 0x40026df6:0x3ffbfaf0 0x4002a77d:0x3ffc7fb0 0x400815e0:0x3ffc8000 0x4008136d:0x3ffc8020 0x40081469:0x3ffc8040 0x40081213:0x3ffc8060 0x40081ee5:0x3ffc8080

As I already said, Im not an expert with I2C. My plan is to connect two more slave devices to the bus in the future. But it already doesnt work properly with two slave devices… What did I wrong? What can cause a reboot of the master device? If im testing the connection to each device separately (point 1 and point 2), everything works as expected. I was playing around with the I2C clock frequency, but without success. A lower frequency will cause a reboot of the master device more often, a higher frequency causes more errors with reading the RTC.

Any Ideas?

Best regards

Hi, its me again.
I was testing now for two hours. The configuration ESP32S2 (master) and DS3231 (slaves) works without any issues. Im still requesting the time every second and printing the output at the serial monitor. The configuration ESP32S2 (master) and ESP8266 (slave) is also working very well for two hours without any problems. The random reboot of the master only occurs with two devices in slave configuration.

Any idea how I can handle the problem? I still want to use I2C to communicate between the devices, not wifi or anything else. If the problem cant be solved, because of the ESP8266, I will buy an other µC. Any ideas for alternatives?

The master ESP32S2 will send a command to the slave device. Nothing special, anything simple. The slave device have to be good enough to control a NeoPixel with about 400 Leds. I thought it is a good Idea with the ESP32S2 and ESP8266 combination, but im open for (cheap and small size) alternatives.

Thank you very much!

The ESP32-S2 and the ESP8266 are single core. A sketch could lock it up so it does not have time to run the Wifi and other things.
The ESP32-S2 might have a few bugs, because it is new and less often used. The Arduino libraries for the ESP8266 and ESP32 have been improved the past years.

seackone:
I still want to use I2C to communicate between the devices

No, you don't :wink:

I think that two ESP32 with Serial/UART communication is better.
I wrote this page to scare new users: How to make a reliable I2C bus · Koepel/How-to-use-the-Arduino-Wire-library Wiki · GitHub. You don't have different voltage levels, but there are enough other problems.

The Serial communication does not waste time.
The I2C communication is blocking and waits until the I2C is fully finished before the function returns. So you have a 240MHz processor, doing nothing.

When you have a problem with the RTC communication, then something is wrong. The I2C bus is not fault tolerant. It should work 100% all the time. Do you use a breadboard with bad contacts ?

Do you still want to use I2C between the ESP processors ? Is there something else that I can say to convince you not to do that ?

Hello Koepel, thank you very much for your response!

Koepel:
When you have a problem with the RTC communication, then something is wrong. The I2C bus is not fault tolerant. It should work 100% all the time. Do you use a breadboard with bad contacts ?

I dont have any issues with the RTC or with the ESP8266 in slave configuration, as long as I use only one of them.

I want to realize a battery operated (okay, its a big battery with 200Ah), very energy saving project. Due to the low power requirements, I changed my ESP32 board to the newer version ESP32-S2. Because of the requirement, I also want to avoid wifi and bluetooth (its not longer available at the new board anyway). The new board comes with an other issue: there are only two UART ports implemented. I use one of them for debugging and switching the other UART port to the device I want to read or write (display, temperature sensor...). I also bought the DS3231 RTC, which uses I2C and I thought it is a good idea to use the bus for other things as well due to the limited UART ports.

Koepel:
The ESP32-S2 and the ESP8266 are single core. A sketch could lock it up so it does not have time to run the Wifi and other things. The ESP32-S2 might have a few bugs, because it is new and less often used.

Indeed. That was what I already thought after I did my research about the error message and the interrupt watchdog:

The interrupt watchdog makes sure the FreeRTOS task switching interrupt isn't blocked for a long time. This is bad because no other tasks, including potentially important ones like the WiFi task and the idle task, can't get any CPU runtime.

But what I can not understand: why does it work if I use only one slave device? I always use the same code and just plug or unplug the RTC/ESP8266 in between.. Thank you very much for your wiki. That was exactly what I was looking for during my research about the I2C bus! There is one very important point for my project:

When a Arduino is used as a I2C Slave, then using libraries that turn off interrupts should be avoided. Those libraries are: DHT libraries, OneWire/DallasTemperature, Neopixel and FastLED libraries, and more

Okay, in this content.. I should not use I2C if I want my slave ESP8266 to control a NeoPixel.. hm. But there is an other thing I tested:

"The I2C bus is a bus, so it can go through a cable". The I2C bus was designed to be used on the same pcb board. The I2C bus is not meant to go through a cable. If wires or a short cable is used, then keep SDA away from SCL. The I2C bus can not handle crosstalk between SDA and SCL.

I was using a 30ft telephone cable with four wires and twisted pair. It worked, even if i used the twisted pair for SDA and SCL!

Anyways, maybe I2C is not the best idea for my project and I know: using 400 NeoPixels in a low current environment sounds very odd. But because of their high power consumption, I want to keep the power of all other devices as low as possible. Maybe we can do a short talk about my project to find an other solution:

Im not committed to the ESP32-S2 as master device. I chose the S2 because of the amount of GPIOs, the low power consumption and the not required bluetooth connectivity. What I want to do is communicate with a display (UART) and different sensors (UART and I2C). I need a lot of GPIOs and are already using more UART devices as I previously expected. I also want to control a NeoPixel with an other ESP8266 in slave configuration: Master device sends command like "color, brightness, animation..." to the ESP8266 and he will handle the rest. But the ESP8266 is about 10ft away of the master device (this is the reason why I did the test with the telephone cable). Im very open to any other solutions!

Maybe this could be a possible szenario:
ESP32-S2 = Master device (wifi off)
ESP8266 = Slave device (deep sleep)

The ESP32-S2 is also connected to a display. If there is a person who want to turn on the light, the ESP32-S2 enables wifi in AP mode and sends a wake up pulse to the ESP8266. After the ESP8266 is ready to work, it will connect to the AP and, receive the "light on command" and control the neopixel. The wifi turns off at booth devices after a short time (no user input at the display) and turns on again if a new event occur (pulse by the ESP32-S2 doesnt wake up the ESP8266 in this case, it only activates wifi). Its sounds a bit complicated but shouldnt be a problem. Its just a matter of time, how long it takes to wake up the slave device and receive the request. I dont want to wait a couple of seconds if I want to turn the light on..

30ft = 9 meters :wink:

seackone:
I dont have any issues with the RTC or with the ESP8266 in slave configuration, as long as I use only one of them.

Translated: Others can connect 10 or 20 devices to a I2C bus, but my I2C bus is so terribly bad that I can not even connect 2 devices. Help ! Panic ! Running in circles !

I don't know why there are problems with two devices connected. It should not happen. There can be so many causes.

I think there is a big difference between working well and barely working, therefor I would not put the I2C signals in such a long cable. I don't know how good the ESP8266 is as a I2C Slave. The Arduino Wire library for the Arduino Uno is bug-free since a few years and I'm not sure about the rest.

The Neopixel library turns off interrupts to make the signal with specific timing. When the interrupts are off, the Arduino can not respond as a I2C Slave. It will be okay for 99% of the time, but with a small stress-test, it immediate failed.
The new RP2040 has programmable hardware blocks which can make those Neopixel signals on their own. Things will be better in the future 8)

When using Serial/UART communication, then resistors can be added in the signal line. For example between 100 Ω and 470 Ω, depending on the cable, the baudrate, the currentspikes and the risk you are willing to take.
I have not tried SoftwareSerial on a ESP, but from I read, it works okay. It is not so demanding as SoftwareSerial on a Arduino Uno.

The easiest solution is to use only ESP modules with Wifi, Bluetooth or ESP-NOW. However, I have read that only one of them can be used at the same time (it seems that an other one at the same channels might work).
I have only used Wifi myself so far.

With a 200Ah battery, then any Arduino or ESP board in sleep mode will draw less current then the self-leakage of the battery.

A drawing of everyting with distances might help. Your project seems to get more complex every time you write about it :o

Good morning Koepl,

Koepel:
30ft = 9 meters :wink:

Yes, I know. I made my first youtube video, just for you :slight_smile: Only 10 seconds with the same sketch I posted above. Instead of sending random stuff, I was sending "Das ist ein test" --> "This is a test" over the 10ft cable every second.

https://youtu.be/2cPMS0M4PEg

Sender and receiver are connected to the same DC source but I made other tests where the mac is powering just the slave and 5V / GND is also transfered over the cable to power the master device. But this was just a test... For my explained setup above, everything is directly connected at the breadboard.

Koepel:
Translated: Others can connect 10 or 20 devices to a I2C bus, but my I2C bus is so terribly bad that I can not even connect 2 devices. Help ! Panic ! Running in circles !

Except of panic and running in circles, you are right. Im not in panic, because im not committed to use the I2C bus to communicate with an ESP8266. Im just looking for a solution to find a way, I2C is one of them. But I really dont know why it doenst work with more than one slave device. I think the problem might be the ESP8266. The DS3231 was my first I2C device, I also ordered a I2C temperature sensor but its not delivered yet. So I can not test the bus with two devices (without the ESP8266), to make sure, that the ESP8266 causes the problems.

Koepel:
I think there is a big difference between working well and barely working, therefor I would not put the I2C signals in such a long cable. I don't know how good the ESP8266 is as a I2C Slave. The Arduino Wire library for the Arduino Uno is bug-free since a few years and I'm not sure about the rest.

It have to work well :slight_smile: Im also not committed to the ESP8266, so maybe the arduino pro mini is an alternative for a stable connection. But like I said before, it dont have to be I2C. Software Serial is one possible solution due to the reduced amount of UART ports of the ESP32-S2, but its not implemented yet for this chip. There is already an issue posted at github. Maybe Software Serial works in the future for the ESP32-S2, but not now.

Ive never heard about ESP-NOW and did a very quick google research during my post. That sounds interesting! Thank you for the hint.

My project is actually already running. Here is what I did so far:
Im using a 200Ah LiFePo4 battery in my RV, which is also powering my ESP32-S2 master device. This device is in the most of the time in deep sleep (waking up every minute, reading sensors, save values, going to sleep). There is one exception: the master device is also connected to a HMI display. If the display turns on, the master device will wake up immediately and show all sensor values in real time. I do not use wifi so far, due to the high power consumption. I know, the battery is big, but it doesnt mean that I dont have to save power if I can. I chose the ESP32-S2 because of the low power consumption in operation mode (without wifi) and the amount of GPIOs. At the moment, all sensors that im reading are connected with the UART of the ESP32-S2 and it only have two of them. One is intended for the HMI display, the other one is for the sensors and are switching all the time (in dependence which sensor I want to read). For debugging, I can not use the display... But anyways. I want to extend my setup with a real time clock and an other temperature sensor. Both are using I2C, which I never used before. The RTC is right next to the ESP32-S2 on the same PCB, so I think that is not a problem. The temperature sensor, well... I think there is a distance of 10ft between ESP32-S2 and sensor. This will might cause in trouble, but I have to test it.

The next extension of my setup is to control three different strips with neopixel (already ordered but not delivered yet). Im not very familiar to this as well, they are my first pixels... The longest strip is roughly about 23ft so I do have 350 pixels. I read that the distance between controller and strip have to be as short as possible. That is one reason why the ESP32-S2 can not control the strip directly, because the distance in between is about 10ft. I also want to outsource the controlling task of the pixels to an other microcontroller (my idea was to use the ESP8266), so the master device can do other things. Therefore, im looking for a solution to control the pixels. Im not committed to microcontroller which controls the pixels, as long as it comes with a small pcb size and can handle 350 up to 400 pixels (need enough storage). Im also not committed to the way of data transmission between master and slave device, as long as it is low power (see my idea in my previous post with turning wifi on and off).

Im open for any ideas! For the two slave I2C problem... I guess that I have to wait for my I2C temperature sensor. I think the ESP8266 could be causing the problem.

Thanks for the video. That is a very clean test-setup.

I suggest to use the I2C bus only for sensors around the ESP or Arduino board.

Serial/UART in a car or RV ? Perhaps you also need a shielded cable and a RS-485 or CAN bus. I think that RS-485 is the best option.
For example a MKR board with a RS-485 shield: Arduino MKR 485 Shield | Arduino Official Store. That will be a good solution.

Using ESP modules with wireless communication is probably the best solution. Then any ESP8266 or ESP32 or ESP32-S2 should work and new modules can be added later on. Even if you power a ESP module via a cable, then it is normal to use wireless for communication.
The ESP modules might need a peak of 250mA when using Wifi. That could drop the voltage when the power has to go through a cable. But since the ESP processors run at 3.3V, the voltage is allowed to drop almost down to 3.3V (I think, not 100% sure).

Be careful with ground currents. A loop with ground wires can become an antenna. When there are two paths for the ground, the ground current can decide to take the thinner wire.

Hi Koepel,
thank you very much again for your response and the hint with ESP-NOW. I never heard about it and I think that is exactly what I was looking for. I love the videos of Andreas Spiess. Very well explained.

I just need one extra pin to wake up the slave device, but I need wires for the power supply anyway. After I2C was not working as expected, I was thinking about a short wifi connection between master and slave. The only thing I was wondering: how long does it take to power up the slave device, connect to the master and receive a message. Mr. Spiess was measuring the time and it took him about 7 seconds. Too long for a light switch. But with ESP-NOW, it was just a few milliseconds. Perfect! There are only some limitations with the data size to transfer, but I only have very small packages to transmit.

I also ordered and I2C temperature sensor, which will be placed 10ft away of the master device. Maybe im doing here exactly the same as with the light example: using a slave device (esp8266) to read the temperature and send it to the master with ESP-NOW.

Koepel:
Serial/UART in a car or RV ? Perhaps you also need a shielded cable and a RS-485 or CAN bus. I think that RS-485 is the best option. For example a MKR board with a RS-485 shield: Arduino MKR 485 Shield | Arduino Official Store. That will be a good solution.

Actually, my first plan was to use cat7 cable to connect master and slave device for I2C communication. When I was looking for the cat7 cable in my cable box, I found the telephone cable first and gave it a try. It wasnt the plan but it worked :slight_smile: And thank you again for the next hint wis RS-485. I never used it before but I was already reading about it. If im running into trouble with ESP-NOW, I will try this solution next!

Koepel:
Be careful with ground currents. A loop with ground wires can become an antenna. When there are two paths for the ground, the ground current can decide to take the thinner wire.

I know. I think you can not see it in the video I uploaded to youtube. The shield of the cable was only connected at one side to ground (at the master device) and left open at the slave device to avoid an antenna. Ive learned that lesson in my apprenticeship decades ago... But that is a good point. The setup in the video does not work if the shield of the cable is not connected to ground!
I will try ESP-NOW next and write my progress here. Thank you very much, I really appreciate your help!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.