I am using a CCS811 VOC and CO2 sensor, a BMP Pressure and Temperature sensor and an Adafruit SSD1306 OLED display with an Adafruit ESP32 Huzzah. All the sensors and display use i2c communications. If I run my code in the “stand alone” mode, i.e. not using Blynk, everything works fine. If I use Blynk, after some minutes up to several hours of operation, I get the following i2c errors:
[esp32-hal-i2c.c:161] i2cWrite():Busy Timeout! Addr:5b.
[esp32-hal-i2c.c:161] i2cWrite():Busy Timeout! Addr:40.
[esp32-hal-i2c.c:161] i2cWrite():Busy Timeout! Addr:5b.
I tried removing the display – same result.
I removed one sensor and removed the display – same result with Blynk.
I have read in other forums that the i2c on the ESP32 has some problems with timing but the fact that it works without Blynk leads me to believe that I must be doing something wrong with Blynk.
My code is below. I cleaned it up a bit by removing some of the functions to make it easier to read and this code works without Blynk and fails with Blynk.
/******************************************************************************
Read the TVOC and CO2 values from the SparkFun CSS811 breakout board
Originally derived from Sparkfun ESP32 Thing example
******************************************************************************/
#include <arduino.h>
#include "SparkFunCCS811.h"
#include <SPI.h>
#include <Wire.h> //Classes for I2C
#include <Adafruit_GFX.h> //Classes for display
#include <Adafruit_SSD1306.h> //Classes for OLED display
/*******************************************************************
*
* The following lines are for connecting to Blynk
*
*******************************************************************/
#include <WiFi.h> //
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
// This is my authorization code for Blynk
char auth[] = “xxxxxxxxx”;
//Put router info here
char ssid[] = “xxxxxxxxx”;
char pass[] = “xxxxxxxxxx”;
BlynkTimer timer;
/**********************************************************************************************/
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define CCS811_ADDR 0x5B //Default I2C Address for the CCS811
//#define CCS811_ADDR 0x5A //Alternate in case I have a conflict with others
CCS811 SensorOBJ(CCS811_ADDR); //Sensor object of class CCS811
long chipid; //used if I want to display chip identification code
long NewTime = 0; //upddated millisecond count
int GoofOff = 50; //delay time in milliseconds
void oledDisplay(); //function prototype declaration
void sendSensor(); //function prototype declaration
void setup()
{
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
Serial.begin(115200);
CCS811Core::status returnCode = SensorOBJ.begin(); // used for error codes
Serial.print("begin exited with: ");
Serial.println();
display.clearDisplay();
Blynk.begin(auth, ssid, pass); // start up Blynk
// this uploads data from sensor to Blynk at 1 second intervals
timer.setInterval(1000L, sendSensor);
//timer.setInterval(2307L, oledDisplay); // skew timer interval to stop i2c issues
}
void loop()
{
Blynk.run();
timer.run();
//call function if Blynk is disabled
//oledDisplay();
//delay(1000);
}
void oledDisplay(){
SensorOBJ.readAlgorithmResults(); //get data from Sensor
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("TVOC: ");
display.println( SensorOBJ.getTVOC());
display.print("CO2: ");
display.println( SensorOBJ.getCO2());
display.display(); //Write data to oled
//display.clearDisplay();
}
void sendSensor(){
if (SensorOBJ.dataAvailable()){
Serial.println("Sending Data");
SensorOBJ.readAlgorithmResults();
int C = SensorOBJ.getCO2();
int V = SensorOBJ.getTVOC();
Blynk.virtualWrite(V0, C);
Blynk.virtualWrite(V1, V);
}
}
Could someone give me an idea as to what I should do?
My experience with using the ESP32 is basically a bleeding edge process and things will go wonky…
The ESP32 is a dual core MCU, with unique timing issues that seem to still be a work in progress… as indicated by lack of analogWrite() commands and such.
Blynk also requires constant timing and communication, so there is bound to be some conflicts over time… but whether the issue is Blynk or espressif is hard to determine… but my bet is on the ESP32 Arduino core and espressif due to the still immature age of the port.
As to suggestions… sorry, the ESP32 is still too new to me to dig into the nitty gritties One of mine runs 24/7 and disconnects from Blynk Server without errors or stopping the sketch at random times days, weeks… and this is without using i2C, but it is with using ledcSetup, so probably something with the core timing.
Thanks for the quick reply, Gunner. I sort of suspected this was going to be the answer, but I am an eternal optimist.
The issue with core timing is probably correct – further evidence of that is once the error occurs, the ESP32 continues giving the error message and can’t push data to Blynk until I reset it, although it is still connected to Blynk. I
have used the ESP32 with Blynk for some months now without i2c and have had no serious issues.
A GitHub user going by the name stickbreaker has been doing a lot of work to improve I2C on Arduino ESP32. His work is currently being reviewed and there might be some API changes still but the code can be tested from a development branch created for his work. https://github.com/espressif/arduino-esp32/tree/stickbreaker-i2c
Unfortunately I can’t help with how to install this version instead of the official one but I’ve read several people commenting it has fixed most of their I2C related issues.
Hello Ristomatti. I went to stickbreaker’s GitHub, and after reading through his explanations, I am now using his code. As of now, I have the ESP32, CCS811 and the OLED display working with Blynk with no failures for two days now! Before, the longest was about 2 hours. Thank you very much for your suggestions.
To be safe, I would recommend renaming the old cores and old Wire folders just in case something blows up. Stickbreaker says this is a Beta version, so things may change and blow your stuff up.
Also, I am running into a bit of a problem in that I get a random failure every day or so. I think I may have a noise issue on the i2C bus, so I am going to clean up the board and keep monitoring this.
Here are some links to the background information that I found useful:
@flyindon Great to hear that it helped! I haven’t actually ended needing it but your post just reminded me about this. It’s useful to occasionally check the arduino-esp32 GitHub issue threads to see how things are progressing.
Hi flyindon,
I’m suffering a similar problem to that you describe. I have an ESP32 monitoring analog (light, wind-speed and temperature) and digital (temperature, humidity, barometric pressure) sensors for environmental monitoring. The program runs fine without Blynk (i.e. reporting to the serial port). When I implement Blynk, it disconnects from the wifi randomly, and the serial output shows that it hangs on one of the digital sensors (suggesting an I2C issue). If I comment out the digital sensors, and just monitor the analog sensors, Blynk runs with no problems. Your solution sounds like the right thing, but I’m not sure how to implement it. I can’t see how to download files from the Github links that you indicate above. What am I missing? I’m a newbie at this, so thanks for steering me in the right direction.
I am out of town for a few days and away from my computer. I understand that Stickbreaker’s fixes hace been incorporated into espressif, so get the update from espressif. If you still have problems, I can try to help later this week.
Don,
Thanks so much. I do have a very recent espressif implementation, so I guess that the Stickbreaker’s fixes are already in. In the meantime I believe that I have found a fix, or at least a work-around. My initial sketch called ‘readSensors’ as a function that read each sensor and wrote its value to a Blynk virtual pin sequentially. I wondered if the BlynkWrite function at the end of each sensor ‘module’ interfered with the I2C timing, so I placed all the BlynkWrite commands after reading all the sensors. So far no disconnect, so that’s good. Whether my reasoning is sound, I’m not sure, but the net result is what I hoped for. Thanks for your offer to help.
I’m using an OLED with relevant Adafruit Libraries to display my Can Bus Data onto the OLED and send it to Blynk for remote monitoring.
I went to a friend’s house to demo the software and was met with an OLED that displays absolute garbage - obviously my ESP32 didn’t connect to his network.
I started my software back at my place and double checked that everything is working, which it was until I switched off my wifi router.
I’m making use of Blynk v2.0.
I’m a bit confused as to how the blink library can cause timing issues on the I2C.
My Can Bus as well as my FreeRTOS tasks are running as should when the wifi is disconnected, any advice on what to try?
I went through the article, and made two adjustments in the Settings.h file:
#else
// Custom board configuration
#define BOARD_BUTTON_PIN 0 // Pin where user button is attached
#define BOARD_BUTTON_ACTIVE_LOW true // true if button is "active-low"
#define BOARD_LED_PIN 27 // Set LED pin - if you have a single-color LED attached
//#define BOARD_LED_PIN_R 27 // Set R,G,B pins - if your LED is PWM RGB
//#define BOARD_LED_PIN_G 26
//#define BOARD_LED_PIN_B 25
//#define BOARD_LED_PIN_WS2812 33 // Set if your LED is WS2812 RGB
#define BOARD_LED_INVERSE false // true if LED is common anode, false if common cathode
#define BOARD_LED_BRIGHTNESS 64 // 0..255 brightness control
#endif
I’m making use of the ESP32 DevKit v4.
My code reacts in exactly the same manner as explained above:
When the Wifi connection drops, the OLED immediately displays garbage.
I have noticed the following in ConfigMode.h:
void enterError()
{
BlynkState::set(MODE_ERROR);
unsigned long timeoutMs = millis() + 10000;
while (timeoutMs > millis() || g_buttonPressed)
{
delay(10);
app_loop();
if (!BlynkState::is(MODE_ERROR)) {
return;
}
}
DEBUG_PRINT("Restarting after error.");
delay(10);
restartMCU();
}
When the wifi connection is restored, and only after the MCU restarts, the MCU reconnects to the blynk server and my OLED displays the information correctly.
I have tested this theory by commenting the //restartMCU(); function - the MCU does not restart, the OLED displays garbage and it does not reconnect to the blynk server.
My Can Bus and other RTOS related tasks run without errors.
What will cause the processor to enter the error state and cause my I2C to be affected?