Strange i2c behavior with esp32 and Blynk

Michael,

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

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.

Michael

I have a very similar issue at the moment.

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?

Are you using the Edgent example?

Pete.

Correct.

You should read this…

especially the “Defining your physical switch and LED” section, then check that you don’t have a GPIO conflict.

Pete.

1 Like

Thanks.

1 Like

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?

Thanks,
Shawn

Here is my schematic of the setup - as far as my knowledge goes, there aren’t any GPIO conflitcs.

I meant GPIO conflicts within the sketch - Edgent trying to use the same GPIOs as your code.

Pete.

Hi Pete, I have a question.

I noticed that my ESP32 does not reconnect to the wifi after the connection has been restored.

Instead it enters the default error state:

  void run() 
  {
    app_loop();
    switch (BlynkState::get()) 
    {
      case MODE_WAIT_CONFIG:       
      case MODE_CONFIGURING:       enterConfigMode();    break;
      case MODE_CONNECTING_NET:    enterConnectNet();    break;
      case MODE_CONNECTING_CLOUD:  enterConnectCloud();  break;
      case MODE_RUNNING:           runBlynkWithChecks(); break;
      case MODE_OTA_UPGRADE:       enterOTA();           break;
      case MODE_SWITCH_TO_STA:     enterSwitchToSTA();   break;
      case MODE_RESET_CONFIG:      enterResetConfig();   break;
      default:                     enterError();         break;

      Serial.println(BlynkState::get());
    }
  }
};

I changed the timeout time to 30000ms in hopes that it will reconnect, but no luck. The processor restarts.

void enterError() 
{
  BlynkState::set(MODE_ERROR);
  
  unsigned long timeoutMs = millis() + 30000;
  while (timeoutMs > millis() || g_buttonPressed)
  {
    delay(10);
    app_loop();
    if (!BlynkState::is(MODE_ERROR)) 
    {
      return;
    }
  }
  DEBUG_PRINT("Restarting after error.");
  delay(10);

  restartMCU();
}

I’ve also noticed that this line of code sets the status to error, but it’s not checked within BlynkEdgent.h:

BlynkState::set(MODE_ERROR); - where is this mode checked?

My other question is, what might cause the processor to stay in the error mode? I see that app_loop(); method/function is called after every 10ms, but I don’t see any related code within the app_loop(); to reconnect once the connection has been lost nor any other related code which might clear the error.

In the original sketch, it is just the timer that runs:

void app_loop() 
{
    timer.run();
}

In my sketch, I have added my Can Bus task, my Relay Task and my Scheduler. I will remove these and add them to their own RTOS tasks, but doubt this is the reason why my ESP stays in the error mode:

Edgent BlynkEdgent;
BlynkTimer timer3;

void app_loop() 
{
    can_rx();
    timer3.run();
    relay1Task();
    //manual_control();
    startScheduler();
}

Thanks,
Shawn

Are you using EEPROM, SPIFFS, LittleFS etc. in your custom code?

Pete.

Hi Pete,

None of the above.

It’s just I2C, Can Bus and my GPIO’s set as inputs and outputs.

I read an article on RandomNerdTutorials on which pins can and can’t be used and believe I utilized them correctly.

I also noticed that my LED does not flash when the wifi is disconnected - just noticed from a tutorial that the LED will flash when the wifi is not connected on the ESP.

Thanks,
Shawn

Does the LED flash at all?
It should flash rapidly when you press the button for 10 seconds, then go into provisioning mode to allow you to input new WiFi credentials in the app.

Pete.

Is PWM used to flash the LED?

I think so, but pin 27 is PWM capable.

Pete.

I have discovered this code:

#elif defined(BOARD_LED_PIN)       // Single color LED

  void initLED() 
  {
    ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_BITS);
    ledcAttachPin(BOARD_LED_PIN, LEDC_CHANNEL_1);
  }

in Indicator.h -

My LED seems to flash, but it is barely noticeable.

I have also made some changes to the following code in the function call void enterConnectNet() located in ConfigMode.h:

WiFi.begin(configStore.wifiSSID, configStore.wifiPass);

  unsigned long timeoutMs = millis() + WIFI_NET_CONNECT_TIMEOUT;
  while ((timeoutMs > millis()) && (WiFi.status() != WL_CONNECTED))
  {
    delay(10);
    app_loop();
    if (!BlynkState::is(MODE_CONNECTING_NET)) 
    {
      WiFi.disconnect();
      return;
    }
  }

I have changed the WIFI_NET_CONNECT_TIMEOUT to 60000 in Settings.h. This gives the ESP enough time to reconnect after I switched the wifi off and then back on again.

I will change this code, as this will set the following line of code BlynkState::set(MODE_ERROR); if the Wifi is not restored fast enough (or not at all).

This will cause the processor to restart and continuously restart if the Wifi connection is not restored, which leaves your application at the mercy of the internet - (not ideal when you are living in a country which has serious power delivery issues like South Africa).

Also note that this function, once again calls the app_loop() function which I only have the Blynk Timer running, nothing else.

I have a theory as to why my OLED displays garbage the moment my Wifi connection drops: The Wifi.h library is continuously trying to reconnect to the Wifi router, that it interrupts the I2C process and my bit timings gets thrown off.

It’s either that or something else in the Blynk framework I am missing.

If someone from Blynk can please assist, it will be greatly appreciated.

In the meantime I will replicate the above with only using the Wifi.h library and the relevant Adafruit libraries necessary to display output on the OLED.

Thanks,
Shawn

You could change the brightness in Settings.h to 1023, or maybe your series resistor value is wrong?

The Blynk staff that are likely to be able to advise are Ukrainians, living in the Ukraine. They have more pressing issues to deal with at the moment :confused:

Pete.

I did not realize that is the situation.

I’m really sorry.

I did some more research and turns out I have to pin my tasks to core 1:

  /* FreeRTOS Related Code */
  //Binary Semaphore for I2C
  xI2CSemaphore = xSemaphoreCreateBinary();  
  //FreeRTOS Tasks
  xTaskCreate(genTask, "genTaskE", 2048, NULL, 3, NULL);
  xTaskCreatePinnedToCore(oledUpdate,  "oledUpdateE", 32768, NULL,  5, NULL, 1);
  xTaskCreatePinnedToCore(rtcTask,  "rtcTaskE", 8192, NULL,  5, NULL, 1);
  xTaskCreate(manualCtrl, "manualCtrlE", 8192, NULL, 7, NULL);
  //xTaskCreate(CanBus, "CanBusE", 16384, NULL, 6, NULL);

I will run this in conjunction with the Blynk related code and report back on my findings.

1 Like

I can confirm my code is working 100% by moving my I2C to core 1.

Now I just have to figure out as to why my Can Bus stopped working and I continuously get error 702.

1 Like